Scroll to last item or specific item uwp

IVANLABRADORIVANLABRADOR USMember ✭✭

Hello I'm trying to get to the end of a listview when I load the page but UWP does not seem to do anything, I do not know if I'm missing something. This is my code:

        protected override void OnAppearing()
        {
            base.OnAppearing();
            List<TransactionsViewModel> someVar = ((IEnumerable<TransactionsViewModel>)ListViewSH.ItemsSource).ToList();
            Device.BeginInvokeOnMainThread(() =>
            {
                ListViewSH.ScrollTo(someVar
                    [someVar.Count - 1], ScrollToPosition.End, false);
            });
        }

Best Answer

Answers

  • IVANLABRADORIVANLABRADOR USMember ✭✭
    edited June 8

    @JohnHardman said:

    @IVANLABRADOR said:
    Hello I'm trying to get to the end of a listview when I load the page but UWP does not seem to do anything, I do not know if I'm missing something.

    The issue is that your ListView C# object has been created, but the ListView instance has not yet been through the layout phase of the rendering process. Until that has been done, scrolling will not work

    The solution is to change your OnAppearing() method to be async

            protected override async void OnAppearing()
    

    and then implement a wait before doing the scroll. I have a helper class called ScrollHelper that contains such methods. So, I add the following call before the attempt to scroll.

            await ScrollHelper.WaitForViewToBeInNativeLayout(_listView, 10, 200);
    

    The implementation of that method is:

            public static async Task WaitForViewToBeInNativeLayout(
                View view,
                int millisecondDelay = 1,
                int maxCycles = 10)
            {
                if (view != null)
                {
                    // Note that IsInNativeLayout is currently marked for Xamarin internal use only
                    int cycle = 0;
                    while ((!view.IsInNativeLayout) && (++cycle <= maxCycles))
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(millisecondDelay));
                    }
                }
            }
    

    I have various other methods in that helper class so that all of my calls to ScrollTo and ScrollToAsync are done there. That way, the various XF bugs relating to scrolling that have existed over the last few years have all been handled in one place. Also, if IsInNativeLayout is ever made private or removed completely, the workaround will only need to be applied in that one file.

    BTW, you shouldn't need the Device.BeginInvokeOnMainThread that you have in your code snippet above.

    Hello, you had all the reason, the way you have shown me now if there is a UWP displacement at the end of the list that was what I needed, the only thing is that I thought that the page could be opened and the list already loaded with the last item, what happens now is that the page is loaded first with the list and then with a small delay moves to the end, will there be a way to eliminate that delay as it happens in Android? I share what I did with your suggestion:

     protected override async void OnAppearing()
            {
                base.OnAppearing();
    
                List<TransactionsViewModel> someVar = ((IEnumerable<TransactionsViewModel>)ListViewSH.ItemsSource).ToList();
    
                if (Device.RuntimePlatform == Device.UWP)
                {
                    await ScrollHelper.WaitForViewToBeInNativeLayout(ListViewSH, 1, 10);
                    ListViewSH.ScrollTo(someVar[someVar.Count - 1], ScrollToPosition.End, true);
                }
    
                if (Device.RuntimePlatform == Device.Android)
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ListViewSH.ScrollTo(someVar
                            [someVar.Count - 1], ScrollToPosition.End, false);
                    });
                }
            }
    
  • JohnHardmanJohnHardman GBUniversity mod

    @IVANLABRADOR

    Don't forget that you can remove the Device.BeginInvokeOnMainThread

    I recommend doing the WaitForViewToBeInNativeLayout for all target platforms, rather than only doing it for UWP.

    Regarding the delay, remember that ListView does virtualisation, but how it operates if you say ScrollTo the last item is unknown - that would require checking the XF source code. Does it have to create ViewCells for all items, rather than just those visible at the end of the list? I don't know without checking. I suspect that how ScrollTo operates may vary between platforms, and may vary depending on which caching mode you have specified for the ListView. But, as I said, I haven't checked. Also, remember that the ListView caching on UWP is inconsistent with other platforms. I raised a bug long ago regarding this, but I don't think the inconsistency has ever been fixed. You might want to experiment with caching modes to see what difference they make in your scenario, but check on all platforms due to the inconsistencies.

Sign In or Register to comment.