Restoring exact scroll position of a listbox in Wi

2019-01-17 17:56发布

问题:

I'm working on making an app come back nicely from being tombstoned. The app contains large listboxes, so I'd ideally like to scroll back to wherever the user was while they were scrolling around those listboxes.

It's easy to jump back to a particular SelectedItem - unfortunately for me, my app never needs the user to actually select an item, they're just scrolling through them. What I really want is some sort of MyListbox.ScrollPositionY but it doesn't seem to exist.

Any ideas?

Chris

回答1:

You need to get hold of the ScrollViewer that is used by the ListBox internally so you can grab the value of the VerticalOffset property and subsequently call the SetVerticalOffset method.

This requires that you reach down from the ListBox through the Visual tree that makes up its internals.

I use this handy extension class which you should add to your project (I've gotta put this up on a blog because I keep repeating it):-

public static class VisualTreeEnumeration
{
    public static IEnumerable<DependencyObject> Descendents(this DependencyObject root, int depth)
    {
        int count = VisualTreeHelper.GetChildrenCount(root);
        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(root, i);
            yield return child;
            if (depth > 0)
            {
                foreach (var descendent in Descendents(child, --depth))
                    yield return descendent;
            }
        }
    }

    public static IEnumerable<DependencyObject> Descendents(this DependencyObject root)
    {
        return Descendents(root, Int32.MaxValue);
    }

    public static IEnumerable<DependencyObject> Ancestors(this DependencyObject root)
    {
        DependencyObject current = VisualTreeHelper.GetParent(root);
        while (current != null)
        {
            yield return current;
            current = VisualTreeHelper.GetParent(current);
        }
    }
}

With this available the ListBox (and all other UIElements for that matter) gets a couple of new extension methods Descendents and Ancestors. We can combine those with Linq to search for stuff. In this case you could use:-

ScrollViewer sv = SomeListBox.Descendents().OfType<ScrollViewer>().FirstOrDefault();