using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace LaDOSE.DesktopApp.Behaviors
{
///
/// A sync behaviour for a multiselector.
///
public static class MultiSelectorBehaviours
{
public static readonly DependencyProperty SynchronizedSelectedItems = DependencyProperty.RegisterAttached(
"SynchronizedSelectedItems", typeof(IList), typeof(MultiSelectorBehaviours), new PropertyMetadata(null, OnSynchronizedSelectedItemsChanged));
private static readonly DependencyProperty SynchronizationManagerProperty = DependencyProperty.RegisterAttached(
"SynchronizationManager", typeof(SynchronizationManager), typeof(MultiSelectorBehaviours), new PropertyMetadata(null));
///
/// Gets the synchronized selected items.
///
/// The dependency object.
/// The list that is acting as the sync list.
public static IList GetSynchronizedSelectedItems(DependencyObject dependencyObject)
{
return (IList)dependencyObject.GetValue(SynchronizedSelectedItems);
}
///
/// Sets the synchronized selected items.
///
/// The dependency object.
/// The value to be set as synchronized items.
public static void SetSynchronizedSelectedItems(DependencyObject dependencyObject, IList value)
{
dependencyObject.SetValue(SynchronizedSelectedItems, value);
}
private static SynchronizationManager GetSynchronizationManager(DependencyObject dependencyObject)
{
return (SynchronizationManager)dependencyObject.GetValue(SynchronizationManagerProperty);
}
private static void SetSynchronizationManager(DependencyObject dependencyObject, SynchronizationManager value)
{
dependencyObject.SetValue(SynchronizationManagerProperty, value);
}
private static void OnSynchronizedSelectedItemsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
{
SynchronizationManager synchronizer = GetSynchronizationManager(dependencyObject);
synchronizer.StopSynchronizing();
SetSynchronizationManager(dependencyObject, null);
}
IList list = e.NewValue as IList;
Selector selector = dependencyObject as Selector;
// check that this property is an IList, and that it is being set on a ListBox
if (list != null && selector != null)
{
SynchronizationManager synchronizer = GetSynchronizationManager(dependencyObject);
if (synchronizer == null)
{
synchronizer = new SynchronizationManager(selector);
SetSynchronizationManager(dependencyObject, synchronizer);
}
synchronizer.StartSynchronizingList();
}
}
///
/// A synchronization manager.
///
private class SynchronizationManager
{
private readonly Selector _multiSelector;
private TwoListSynchronizer _synchronizer;
///
/// Initializes a new instance of the class.
///
/// The selector.
internal SynchronizationManager(Selector selector)
{
_multiSelector = selector;
}
///
/// Starts synchronizing the list.
///
public void StartSynchronizingList()
{
IList list = GetSynchronizedSelectedItems(_multiSelector);
if (list != null)
{
_synchronizer = new TwoListSynchronizer(GetSelectedItemsCollection(_multiSelector), list);
_synchronizer.StartSynchronizing();
}
}
///
/// Stops synchronizing the list.
///
public void StopSynchronizing()
{
_synchronizer.StopSynchronizing();
}
public static IList GetSelectedItemsCollection(Selector selector)
{
if (selector is MultiSelector)
{
return (selector as MultiSelector).SelectedItems;
}
else if (selector is ListBox)
{
return (selector as ListBox).SelectedItems;
}
else
{
throw new InvalidOperationException("Target object has no SelectedItems property to bind.");
}
}
}
}
public class TwoListSynchronizer : IWeakEventListener
{
private static readonly IListItemConverter DefaultConverter = new DoNothingListItemConverter();
private readonly IList _masterList;
private readonly IListItemConverter _masterTargetConverter;
private readonly IList _targetList;
///
/// Initializes a new instance of the class.
///
/// The master list.
/// The target list.
/// The master-target converter.
public TwoListSynchronizer(IList masterList, IList targetList, IListItemConverter masterTargetConverter)
{
_masterList = masterList;
_targetList = targetList;
_masterTargetConverter = masterTargetConverter;
}
///
/// Initializes a new instance of the class.
///
/// The master list.
/// The target list.
public TwoListSynchronizer(IList masterList, IList targetList)
: this(masterList, targetList, DefaultConverter)
{
}
private delegate void ChangeListAction(IList list, NotifyCollectionChangedEventArgs e, Converter