It seems that the versatility of WPF ListView does not allow the class to provide a property similar to TopItem WinForms. However, if the instance is configured with VirtualizingStackPanel , you can still query the superscript directly. This avoids the search and iteration required by other approaches. (The approach is based on this post .)
I think the hit test method used in the accepted answer is more general, but if you really need a list index, not a list item, this can save the IndexOf call.
My application needed to save and restore the position of the list after making significant changes to the contents of the list. The code for setting the top position (based on this post ) is also shown below. For convenience, they are implemented as extension methods.
public static class ListViewExtensions { public static int GetTopItemIndex(this ListView lv) { if (lv.Items.Count == 0) { return -1; } VirtualizingStackPanel vsp = lv.GetVisualChild<VirtualizingStackPanel>(); if (vsp == null) { return -1; } return (int) vsp.VerticalOffset; } public static void ScrollToTopItem(this ListView lv, object item) { ScrollViewer sv = lv.GetVisualChild<ScrollViewer>(); sv.ScrollToBottom(); lv.ScrollIntoView(item); } }
The extremely handy GetVisualChild method from the MSDN publication :
public static class VisualHelper { public static T GetVisualChild<T>(this Visual referenceVisual) where T : Visual { Visual child = null; for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceVisual); i++) { child = VisualTreeHelper.GetChild(referenceVisual, i) as Visual; if (child != null && child is T) { break; } else if (child != null) { child = GetVisualChild<T>(child); if (child != null && child is T) { break; } } } return child as T; } }
Note on using ScrollToTopItem : ScrollToBottom() takes effect immediately, but it seems that ScrollIntoView() postponed. So if you call GetTopItemIndex() right after ScrollToTopItem() , you get the index for the item at the bottom.
source share