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 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 ''' ''' On Selection Changed ''' ''' ''' Private Sub AssociatedObject_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) 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 ''' ''' 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 DataGridControl As DataGrid ''' ''' When Beahvior is attached ''' Protected Overrides Sub OnAttached() MyBase.OnAttached() DataGridControl = Me.AssociatedObject AddHandler Me.AssociatedObject.SelectionChanged, AddressOf AssociatedObject_SelectionChanged End Sub Private Sub AssociatedObject_CollectionChanged(sender As Object, e As System.Collections.Specialized.NotifyCollectionChangedEventArgs) UpdateSelectedItemPosition() 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 'SE SI CAMBIA ITEMSSOURCE PERDE IL RIFERIMENTO E SMETTE DI FUNZIONARE 'PER RIATTIVARLO USARE IL SEGUENTE CODICE COMMENTATO ElseIf Not IsNothing(Me.AssociatedObject.ItemsSource) AndAlso 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 Else UpdateSelectedItemPosition() End If End Sub Private Sub UpdateSelectedItemPosition() If DataGridControl.SelectedItem IsNot Nothing Then Dim SelectedItemIndex As Integer = DataGridControl.Items.IndexOf(DataGridControl.SelectedItem) DataGridControl.Dispatcher.BeginInvoke(DirectCast(Sub() DataGridControl.UpdateLayout() If DataGridControl.SelectedItem IsNot Nothing Then DataGridControl.ScrollIntoView(DataGridControl.SelectedItem) End If End Sub, Action)) If SelectedItemIndex > 0 Then DataGridControl.Dispatcher.BeginInvoke(DirectCast(Sub() DataGridControl.UpdateLayout() DataGridControl.ScrollIntoView(DataGridControl.Items(SelectedItemIndex - 1)) End Sub, Action)) End If If SelectedItemIndex < DataGridControl.Items.Count - 2 Then DataGridControl.Dispatcher.BeginInvoke(DirectCast(Sub() DataGridControl.UpdateLayout() DataGridControl.ScrollIntoView(DataGridControl.Items(SelectedItemIndex + 1)) End Sub, Action)) End If 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