Imports System.ComponentModel Imports System.Collections.Specialized Imports System.Windows Imports System.Windows.Controls.Primitives Public Class ScrollToTopOnItemsSourceChange Public Shared ReadOnly ScrollToTopOnItemsSourceChangeProperty As DependencyProperty = DependencyProperty.RegisterAttached("ScrollToTopOnItemsSourceChange", GetType(Boolean), GetType(ScrollToTopOnItemsSourceChange), New UIPropertyMetadata(False, AddressOf OnScrollToTopOnItemsSourceChangePropertyChanged)) Public Shared Function GetScrollToTopOnItemsSourceChange(ByVal obj As DependencyObject) As Boolean Return CBool(obj.GetValue(ScrollToTopOnItemsSourceChangeProperty)) End Function Public Shared Sub SetScrollToTopOnItemsSourceChange(ByVal obj As DependencyObject, ByVal value As Boolean) obj.SetValue(ScrollToTopOnItemsSourceChangeProperty, value) End Sub Private Shared Sub OnScrollToTopOnItemsSourceChangePropertyChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs) Dim itemsControl = TryCast(obj, ItemsControl) If itemsControl Is Nothing Then Throw New Exception("ScrollToTopOnItemsSourceChange Property must be attached to an ItemsControl based control.") End If Dim descriptor As DependencyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(itemsControl.ItemsSourceProperty, GetType(ItemsControl)) If descriptor IsNot Nothing Then If CBool(e.NewValue) Then descriptor.AddValueChanged(itemsControl, AddressOf ItemsSourceChanged) Else descriptor.RemoveValueChanged(itemsControl, AddressOf ItemsSourceChanged) End If End If End Sub Private Shared Sub ItemsSourceChanged(ByVal sender As Object, ByVal e As EventArgs) Dim itemsControl = TryCast(sender, ItemsControl) DoScrollToTop(itemsControl) Dim collection = TryCast(itemsControl.ItemsSource, INotifyCollectionChanged) If collection IsNot Nothing Then AddHandler collection.CollectionChanged, Sub(o, args) DoScrollToTop(itemsControl) End If End Sub Private Shared Sub DoScrollToTop(itemsControl As ItemsControl) Dim eventHandler As EventHandler = Nothing eventHandler = New EventHandler(Sub() If (itemsControl.ItemContainerGenerator.Status = GeneratorStatus.ContainersGenerated) Then Dim scrollViewer As ScrollViewer = GetVisualChild(Of ScrollViewer)(itemsControl) scrollViewer.ScrollToTop() RemoveHandler itemsControl.ItemContainerGenerator.StatusChanged, eventHandler End If End Sub) AddHandler itemsControl.ItemContainerGenerator.StatusChanged, eventHandler End Sub Private Shared Function GetVisualChild(Of T As Visual)(ByVal parent As DependencyObject) As T Dim child As T = Nothing Dim numVisuals As Integer = VisualTreeHelper.GetChildrenCount(parent) For i = 0 To numVisuals - 1 Dim v = CType(VisualTreeHelper.GetChild(parent, i), Visual) child = If(TryCast(v, T), GetVisualChild(Of T)(v)) If child IsNot Nothing Then Exit For End If Next Return child End Function End Class