Detect when WPF listview scrollbar is at the bottom?
Asked Answered
V

5

15

Is there a way to detect if the scrollbar from the ScrollViewer in a ListView has reached the bottom of the virtual scroll space? I would like to detect this to fetch more items from the server to put into the bound ObservableCollection on the ListView.

Right now I'm doing this:

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!");
    }

}

Is this even correct? I also need to differentiate between the vertical scrollbar causing the event and the horizontal scrollbar causing it (i.e. I don't want to keep generating calls to the server if you scroll horizontally at the bottom of the box).

Thanks.

Vitellus answered 19/8, 2009 at 17:22 Comment(0)
V
10

I figured it out. It seems I should have been getting events from the ScrollBar (<ListView ScrollBar.Scroll="currentTagNotContactsList_Scroll" in XAML) itself, rather than the viewer. This works, but I just have to figure a way to avoid the event handler being called repeatedly once the scrollbar is down. Maybe a timer would be good:

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!");

    }

}
Vitellus answered 19/8, 2009 at 17:40 Comment(1)
ScrollBar.Scroll doesn't exist for ListView in Windows 10 .. how to achieve this requirement in windows 10Bottom
I
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
                        }
                    }
                }
Ibidem answered 1/11, 2015 at 7:2 Comment(1)
The accepted answer did not work for scrolling using the mouse wheel. This one did. So +1.Benzaldehyde
V
10

I figured it out. It seems I should have been getting events from the ScrollBar (<ListView ScrollBar.Scroll="currentTagNotContactsList_Scroll" in XAML) itself, rather than the viewer. This works, but I just have to figure a way to avoid the event handler being called repeatedly once the scrollbar is down. Maybe a timer would be good:

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!");

    }

}
Vitellus answered 19/8, 2009 at 17:40 Comment(1)
ScrollBar.Scroll doesn't exist for ListView in Windows 10 .. how to achieve this requirement in windows 10Bottom
T
4

For UWP I got it like this

<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;
}
Think answered 25/5, 2016 at 7:53 Comment(2)
Also works in WPF, using ScrollChanged="ScrollViewerScrollChangedEvent" ... +1Atonic
@Think exactly where do you put scrollviewer?? as i am having multiple Listviews on single UWP page, how can i relate particular scrollviewer with listview?Lighthearted
P
3

you can try this way:

 <ListView ScrollViewer.ScrollChanged="Scroll_ScrollChanged">

and in Back:

 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!");
    }
Plumbo answered 22/6, 2019 at 8:10 Comment(0)
R
2

Not recommand to use ScrollBar.Scroll , beacause if you scroll the middle wheel of the mouse, it won't work.

ScrollBar.Scroll="currentTagNotContactsList_Scroll"

The following support both right side scroll bar and mouse's wheel scroll.

in listbox's xmal:

                 ScrollViewer.ScrollChanged="ScrollViewer_ScrollChanged"

in 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!");
            }
    }
Reproduction answered 9/2, 2021 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.