using System; using System.Collections; using System.Collections.Specialized; using System.Windows; using System.Windows.Controls; namespace Developpez.Dotnet.Windows.Behaviors { /// /// Fournit des propriétés attachées pour ajouter des fonctionnalités à une ListBox /// public static class ListBoxBehavior { #region SelectedItems /// /// Obtient la valeur de la propriété attachée SelectedItems pour l'objet spécifié /// /// Objet dont on veut obtenir la valeur de la propriété /// La liste d'éléments sélectionnés associée à l'objet spécifié [AttachedPropertyBrowsableForType(typeof(ListBox))] public static IList GetSelectedItems(ListBox listBox) { return (IList)listBox.GetValue(SelectedItemsProperty); } /// /// Définit la valeur de la propriété attachée SelectedItems pour l'objet spécifié /// /// Objet dont on veut définir la valeur de la propriété /// La liste d'éléments sélectionnés associée à l'objet spécifié public static void SetSelectedItems(ListBox listBox, IList value) { listBox.SetValue(SelectedItemsProperty, value); } /// /// Identifiant de la propriété attachée SelectedItems /// public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached( "SelectedItems", typeof(IList), typeof(ListBoxBehavior), new UIPropertyMetadata( null, SelectedItemsChanged)); private static void SelectedItemsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var listBox = o as ListBox; if (listBox == null) return; var oldManager = GetSelectionManager(listBox); if (oldManager != null) { oldManager.Dispose(); listBox.ClearValue(_selectionManagerPropertyKey); } var newValue = (IList)e.NewValue; if (newValue != null) { var manager = new MultiSelectionManager(listBox, newValue); SetSelectionManager(listBox, manager); } } private static MultiSelectionManager GetSelectionManager(DependencyObject obj) { return (MultiSelectionManager)obj.GetValue(_selectionManagerPropertyKey.DependencyProperty); } private static void SetSelectionManager(DependencyObject obj, MultiSelectionManager value) { obj.SetValue(_selectionManagerPropertyKey, value); } private static readonly DependencyPropertyKey _selectionManagerPropertyKey = DependencyProperty.RegisterAttachedReadOnly("SelectionManager", typeof(MultiSelectionManager), typeof(ListBoxBehavior), new UIPropertyMetadata(null)); private class MultiSelectionManager : IDisposable { private readonly ListBox _listBox; private readonly IList _selectedItems; private bool _isUpdatingSource; private bool _isUpdatingTarget; public MultiSelectionManager(ListBox listBox, IList selectedItems) { _listBox = listBox; _selectedItems = selectedItems; _listBox.SelectedItems.Clear(); foreach (var item in _selectedItems) { _listBox.SelectedItems.Add(item); } _listBox.SelectionChanged += ListBoxSelectionChanged; var observableList = _selectedItems as INotifyCollectionChanged; if (observableList != null) observableList.CollectionChanged += SelectedItemsCollectionChanged; } void SelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (_isUpdatingSource) return; try { _isUpdatingTarget = true; if (e.OldItems != null) { foreach (var item in e.OldItems) { _listBox.SelectedItems.Remove(item); } } if (e.NewItems != null) { foreach (var item in e.NewItems) { _listBox.SelectedItems.Add(item); } } } finally { _isUpdatingTarget = false; } } private void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { if (_isUpdatingTarget) return; try { _isUpdatingSource = true; foreach (var item in e.RemovedItems) { _selectedItems.Remove(item); } foreach (var item in e.AddedItems) { _selectedItems.Add(item); } } finally { _isUpdatingSource = false; } } #region Implementation of IDisposable public void Dispose() { _listBox.SelectionChanged -= ListBoxSelectionChanged; var observableList = _selectedItems as INotifyCollectionChanged; if (observableList != null) observableList.CollectionChanged -= SelectedItemsCollectionChanged; } #endregion } #endregion } }