Imports System.Windows.Controls.Primitives
Imports System.ComponentModel


Public Class MultiSelectorBehaviours

   Public Shared ReadOnly SynchronizedSelectedItemsProperty As DependencyProperty = DependencyProperty.RegisterAttached("SynchronizedSelectedItems", GetType(IList), GetType(MultiSelectorBehaviours), New PropertyMetadata(Nothing, AddressOf OnSynchronizedSelectedItemsChanged))
   Public Shared ReadOnly SynchronizationManagerProperty As DependencyProperty = DependencyProperty.RegisterAttached("SynchronizationManager", GetType(SynchronizationManager), GetType(MultiSelectorBehaviours), New PropertyMetadata(Nothing))


   Public Shared Function GetSynchronizedSelectedItems(ByVal dependencyObject As DependencyObject) As IList
      Return CType(dependencyObject.GetValue(SynchronizedSelectedItemsProperty), IList)
   End Function

   Public Shared Sub SetSynchronizedSelectedItems(ByVal dependencyObject As DependencyObject, ByVal value As IList)
      dependencyObject.SetValue(SynchronizedSelectedItemsProperty, value)
   End Sub

   Private Shared Function GetSynchronizationManager(ByVal dependencyObject As DependencyObject) As SynchronizationManager
      Return CType(dependencyObject.GetValue(SynchronizationManagerProperty), SynchronizationManager)
   End Function

   Private Shared Sub SetSynchronizationManager(ByVal dependencyObject As DependencyObject, ByVal value As SynchronizationManager)
      dependencyObject.SetValue(SynchronizationManagerProperty, value)
   End Sub

   Private Shared Sub OnSynchronizedSelectedItemsChanged(ByVal dependencyObject As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
      If e.OldValue IsNot Nothing Then
         Dim synchronizer As SynchronizationManager = GetSynchronizationManager(dependencyObject)
         synchronizer.StopSynchronizing()
         SetSynchronizationManager(dependencyObject, Nothing)
      End If

      Dim list As IList = TryCast(e.NewValue, IList)
      Dim selector As Selector = TryCast(dependencyObject, Selector)

      If list IsNot Nothing AndAlso selector IsNot Nothing Then
         Dim synchronizer As SynchronizationManager = GetSynchronizationManager(dependencyObject)

         If synchronizer Is Nothing Then
            synchronizer = New SynchronizationManager(selector)
            SetSynchronizationManager(dependencyObject, synchronizer)
         End If

         synchronizer.StartSynchronizingList()
      End If
   End Sub

   Private Class SynchronizationManager
      Private ReadOnly _multiSelector As Selector
      Private _synchronizer As TwoListSynchronizer

      Friend Sub New(ByVal selector As Selector)
         _multiSelector = selector
      End Sub

      Public Sub StartSynchronizingList()
         Dim list As IList = GetSynchronizedSelectedItems(_multiSelector)

         If list IsNot Nothing Then
            _synchronizer = New TwoListSynchronizer(GetSelectedItemsCollection(_multiSelector), list)
            _synchronizer.StartSynchronizing()
         End If
      End Sub

      Public Sub StopSynchronizing()
         _synchronizer.StopSynchronizing()
      End Sub

      Public Shared Function GetSelectedItemsCollection(ByVal selector As Selector) As IList
         If TypeOf selector Is MultiSelector Then
            Return (TryCast(selector, MultiSelector)).SelectedItems
         ElseIf TypeOf selector Is ListBox Then
            Return (TryCast(selector, ListBox)).SelectedItems
         Else
            Throw New InvalidOperationException("Target object has no SelectedItems property to bind.")
         End If
      End Function
   End Class
End Class
