Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
926 views
in Technique[技术] by (71.8m points)

wpf - Scroll ListViewItem to be at the top of a ListView

In WPF, I know I can use ListView.ScrollIntoView to scroll a particular item into view, but it will always do the least amount of scrolling so that the item is shown.

How can I make it scroll so that the item I want to show is scrolled to the top of the ListView?

I've thought about calling ScrollIntoView twice, once for the item I want at the top, and once for the last shown item, but I don't know how to find out what the last shown item.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

We can do this by obtaining the ScrollViewer that is present in the ListView's ControlTemplate. If you have access to a ScrollViewer then there are a lot of different scrolling methods exposed.

First, we can create a ListView that we want to add this effect to:

<ListView ItemsSource="{Binding Percents}"
      SelectionChanged="OnSelectionChanged"
      x:Name="uiListView"/>


public List<int> Percents { get; set; }

public Window1()
{
    InitializeComponent();

    Percents = new List<int>();
    for (int i = 1; i <= 100; i++)
    {
        Percents.Add(i);
    }
    this.DataContext = this;
}

We will also need something that we can use to obtain the ScrollViewer from the ListView. I've used something similar to this before to work with custom scrolling, and we can use it here as well.

public static DependencyObject GetScrollViewer(DependencyObject o)
{
    if (o is ScrollViewer)
    { return o; }

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
    {
        var child = VisualTreeHelper.GetChild(o, i);

        var result = GetScrollViewer(child);
        if (result == null)
        {
            continue;
        }
        else
        {
            return result;
        }
    }

    return null;
}

Now, we just need to handle the SelectionChanged event. Because we are trying to scroll an item to the top of the list, the best option is to scroll to the bottom, and then re-scroll up to our selected item. As you said, ScrollIntoView will scroll just until the item is visible, and so once the selected item reaches the top as it scrolls back up, it will cease leaving us with our selected item at the very top of the list.

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;
    scrollViewer.ScrollToBottom();

    uiListView.ScrollIntoView(e.AddedItems[0]);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...