Imports System.Windows.Interactivity Imports System.Collections.Specialized Public Class ScrollIntoViewForListBox Inherits Behavior(Of ListBox) Private ItemsSource As INotifyCollectionChanged Private ListControl As ListBox ''' ''' When Beahvior is attached ''' Protected Overrides Sub OnAttached() MyBase.OnAttached() ListControl = Me.AssociatedObject AddHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged End Sub Private Sub AssociatedObject_CollectionChanged(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) If ListControl.SelectedItem IsNot Nothing Then Dim SelectedItemIndex As Integer = ListControl.Items.IndexOf(ListControl.SelectedItem) ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() If ListControl.SelectedItem IsNot Nothing Then ListControl.ScrollIntoView(ListControl.SelectedItem) End If End Sub, Action)) If SelectedItemIndex > 0 Then ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() ListControl.ScrollIntoView(ListControl.Items(SelectedItemIndex - 1)) End Sub, Action)) End If If SelectedItemIndex < ListControl.Items.Count - 2 Then ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() ListControl.ScrollIntoView(ListControl.Items(SelectedItemIndex + 1)) End Sub, Action)) End If End If End Sub ''' ''' On Selection Changed ''' ''' ''' Private Sub AssociatedObject_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) If IsNothing(ItemsSource) Then Dim CurrItemsSource As IEnumerable = Me.AssociatedObject.ItemsSource ItemsSource = TryCast(CurrItemsSource, INotifyCollectionChanged) AddHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged RemoveHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged ' SE SI CAMBIA ITEMSSOURCE PERDE IL RIFERIMENTO E SMETTE DI FUNZIONARE ' PER RIATTIVARLO USARE IL SEGUENTE CODICE COMMENTATO 'ElseIf ItemsSource IsNot Me.AssociatedObject.ItemsSource Then ' Dim PreviousItemsSourceList As INotifyCollectionChanged = TryCast(ItemsSource, INotifyCollectionChanged) ' RemoveHandler PreviousItemsSourceList.CollectionChanged, AddressOf AssociatedObject_CollectionChanged ' Dim CurrItemsSource As IEnumerable = Me.AssociatedObject.ItemsSource ' ItemsSource = TryCast(CurrItemsSource, INotifyCollectionChanged) ' AddHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged End If End Sub ''' ''' When behavior is detached ''' Protected Overrides Sub OnDetaching() MyBase.OnDetaching() 'RemoveHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged RemoveHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged End Sub End Class Public Class ScrollIntoViewForDataGrid Inherits Behavior(Of DataGrid) Private ItemsSource As INotifyCollectionChanged Private ListControl As DataGrid ''' ''' When Beahvior is attached ''' Protected Overrides Sub OnAttached() MyBase.OnAttached() ListControl = Me.AssociatedObject AddHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged End Sub Private Sub AssociatedObject_CollectionChanged(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) If ListControl.SelectedItem IsNot Nothing Then Dim SelectedItemIndex As Integer = ListControl.Items.IndexOf(ListControl.SelectedItem) ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() If ListControl.SelectedItem IsNot Nothing Then ListControl.ScrollIntoView(ListControl.SelectedItem) End If End Sub, Action)) If SelectedItemIndex > 0 Then ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() ListControl.ScrollIntoView(ListControl.Items(SelectedItemIndex - 1)) End Sub, Action)) End If If SelectedItemIndex < ListControl.Items.Count - 2 Then ListControl.Dispatcher.BeginInvoke(DirectCast(Sub() ListControl.UpdateLayout() ListControl.ScrollIntoView(ListControl.Items(SelectedItemIndex + 1)) End Sub, Action)) End If End If End Sub ''' ''' On Selection Changed ''' ''' ''' Private Sub AssociatedObject_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) If IsNothing(ItemsSource) Then Dim CurrItemsSource As IEnumerable = Me.AssociatedObject.ItemsSource ItemsSource = TryCast(CurrItemsSource, INotifyCollectionChanged) AddHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged RemoveHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged ' SE SI CAMBIA ITEMSSOURCE PERDE IL RIFERIMENTO E SMETTE DI FUNZIONARE ' PER RIATTIVARLO USARE IL SEGUENTE CODICE COMMENTATO 'ElseIf ItemsSource IsNot Me.AssociatedObject.ItemsSource Then ' Dim PreviousItemsSourceList As INotifyCollectionChanged = TryCast(ItemsSource, INotifyCollectionChanged) ' RemoveHandler PreviousItemsSourceList.CollectionChanged, AddressOf AssociatedObject_CollectionChanged ' Dim CurrItemsSource As IEnumerable = Me.AssociatedObject.ItemsSource ' ItemsSource = TryCast(CurrItemsSource, INotifyCollectionChanged) ' AddHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged End If End Sub ''' ''' When behavior is detached ''' Protected Overrides Sub OnDetaching() MyBase.OnDetaching() 'RemoveHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged RemoveHandler ItemsSource.CollectionChanged, AddressOf AssociatedObject_CollectionChanged End Sub End Class