当WPF列表视图滚动条位于底部时如何检测?

15
有没有办法检测在ListView中的ScrollViewer滚动条是否已经到达了虚拟滚动空间的底部?我希望检测到这一点,以便从服务器获取更多项目并将它们放入绑定到ListView上的ObservableCollection中。
现在我正在进行以下操作:
private void currentTagNotContactsList_scrollChanged(object sender, ScrollChangedEventArgs e) {

    ListView v = (ListView)sender;


    if (e.VerticalOffset + e.ViewportHeight == e.ExtentHeight) {
        Debug.Print("At the bottom of the list!");
    }

}

这是否正确?我还需要区分是垂直滚动条导致的事件还是水平滚动条导致的事件(即,如果你在框底水平滚动,我不想不断生成对服务器的调用)。

谢谢。

5个回答

15
//A small change in the "Max's" answer to stop the repeatedly call.
//this line to stop the repeatedly call
ScrollViewer.CanContentScroll="False"

private void dtGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
                {
//this is for vertical check & will avoid the call at the load time (first time)
                    if (e.VerticalChange > 0)
                    {
                        if (e.VerticalOffset + e.ViewportHeight == e.ExtentHeight)
                        {
                            // Do your Stuff
                        }
                    }
                }

被接受的答案在使用鼠标滚轮进行滚动时无效,而这个答案有效。所以点赞。 - Roy2511

10

我解决了。看来我应该从ScrollBar(<ListView ScrollBar.Scroll="currentTagNotContactsList_Scroll"在XAML中)本身获取事件,而不是从viewer获取。这个方法可以用,但我必须想办法避免当滚动条向下拖动时事件处理程序被重复调用。也许一个计时器会很好:

private void currentTagNotContactsList_Scroll(object sender, ScrollEventArgs e) {

    ScrollBar sb = e.OriginalSource as ScrollBar;

    if (sb.Orientation == Orientation.Horizontal)
        return;

    if (sb.Value == sb.Maximum) {
        Debug.Print("At the bottom of the list!");

    }

}

4
在 Windows 10 中,ListView 控件中不存在 ScrollBar.Scroll 方法。如何在 Windows 10 中实现这个功能? - djkpA

4
对于 UWP,我是这样得到的:
<ScrollViewer Name="scroll" ViewChanged="scroll_ViewChanged">
    <ListView />
</ScrollViewer>

private void scroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
    var scrollViewer = (ScrollViewer)sender;
    if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
            btnNewUpdates.Visibility = Visibility.Visible;
}

2
同样适用于WPF,使用ScrollChanged="ScrollViewerScrollChangedEvent" ... +1 - BENN1TH
@dnxit 你应该把ScrollViewer放在哪里?因为我在单个UWP页面上有多个Listviews,我该如何将特定的ScrollViewer与ListView相关联? - ace

3

你可以尝试这种方式:

 <ListView ScrollViewer.ScrollChanged="Scroll_ScrollChanged">

在后端中:

 private void Scroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // Get the border of the listview (first child of a listview)
        Decorator border = VisualTreeHelper.GetChild(sender as ListView, 0) as Decorator;
        // Get scrollviewer
        ScrollViewer scrollViewer = border.Child as ScrollViewer;
        if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
        Debug.Print("At the bottom of the list!");
    }

2
不建议使用 ScrollBar.Scroll,因为如果您滚动鼠标的中间轮,它将无法工作。

ScrollBar.Scroll="currentTagNotContactsList_Scroll"

以下支持右侧滚动条和鼠标滚轮滚动。

在列表框的xmal中:

                 ScrollViewer.ScrollChanged="ScrollViewer_ScrollChanged"

在C#中:

        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
            var listBox = (ListBox)sender;
            var scrollViewer =  (ScrollViewer)VisualTreeHelper.GetChild(listBox, 0);

            if (scrollViewer.VerticalOffset == scrollViewer.ScrollableHeight)
            {
                Console.WriteLine("____At the bottom of the list!");
            }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接