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
}
}