ListView ScrollTo is not scrolling correctly

FableFable DEMember
edited June 2015 in Xamarin.Forms

Hi developers,

I am using several ListView controls in my App, but the ScrollTo method is not working as aspected.
When I call the method to scroll to the last item in the list, the ListView is always scrolling to the item before the last.
I tried different parameters e.g. but the behavior was ever the same on Android (Other platforms I did not tested yet)

Here ist some simple code from one of my ContentPages:

        var messageList = new ListView 
        {
            HorizontalOptions = LayoutOptions.Fill,
            VerticalOptions = LayoutOptions.FillAndExpand,
            ItemTemplate = new DataTemplate(typeof(MessageChatCell)),
            HasUnevenRows = true,
        };

        MessagingCenter.Subscribe<MessageChatViewModel, MessageChatItemModel>(this, "ChatListScrollToItem", (sender, model) =>
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                if (model != null)
                {
                    messageList.ScrollTo(model, ScrollToPosition.MakeVisible, true);
                }                    
            });
        });

        Content = messageList;

Best Answers

Answers

  • stvansolanostvansolano UMInsider, University ✭✭✭

    Hello @FabioP,

    Did you try passing the last item instead? I don't have the details of how you bind your messages with the ListView but you could try get it from the source as the following:

    using System.Linq;
    ....
    
    var lastItem = messageList.ItemsSource.OfType<object>().Last();
    messageList.ScrollTo(lastItem, ScrollToPosition.MakeVisible, true);
    
  • FableFable DEMember

    Hi Esteban,

    i tested your code but it does not work. I got the same behavior as before.

    The binding in my code is done as follows:

                messageList.SetBinding(ListView.ItemsSourceProperty, new Binding("Messages"));
    

    In my ViewModel:

            public ObservableCollection<MessageChatItemModel> Messages
            {
                get { return Model.Messages; }
                set
                {
                    Model.Messages = value;
                    OnPropertyChanged();
                }
            }
    

    I checked out the value of the item I use in the ScrollTo() method in a debug session, and it is definitely the last item of the list.

    So, I am perplexed and have no idea what to do next. Is it a bug ?

  • stvansolanostvansolano UMInsider, University ✭✭✭
    edited June 2015

    Fabio,

    Try ScrollToPosition.End instead. Probably it is scrolling as minimum just to make it visible and it is not enough.

    Let me know

  • FableFable DEMember

    That does not work, the scrolling behavior is always the same :neutral:
    I created and attached a small project that demonstrates that ListView behavior.

    Maybe this is more helpfully :-)

  • FableFable DEMember

    For anyone who habe the same issue: In the meantime I spoke with the support, and we found out that it is working with the ScrollToPosition set to Start.

  • FableFable DEMember

    @diegofrata thanks for the tip. And yes, it really seems to be related to the rendering. Did you started to work on a custom renderer ?

    PS: In my App, the chat functionality is just a small part, so i don't think we work on the same App :smile:

  • DiegoFrataDiegoFrata GBMember ✭✭

    Actually I didn't, I decided to finish the app first, ship it, cash in and maybe fix these issues later. (Any similarity with a certain company's approach to releases is a mere coincidence).

  • KumarsamyKumarsamy USMember

    I am getting this exception "Method 'AbsListView.SetSelectionFromTop' not found."

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭
    edited February 2016

    Any way of doing this through XAML and MVVM binding?
    The problems I'm finding here is that ScrollTo() is a METHOD. If it were a property that could be bound to it would be much easier to use. For Example:</p> <pre><code class="xml"><ListView x:Name="imagesListView" ItemsSource="{Binding PendingScans}" SelectedItem="{Binding SelectedPendingImagePath, Mode=TwoWay}" ScrollToItem="{Binding SelectedPendingImagePath}" Grid.Row="1" Grid.Column="1"></ListView>

  • stvansolanostvansolano UMInsider, University ✭✭✭

    An XF Behavior might be a good candidate to resolve it. Have you tried it?

  • BalakrishnanSBalakrishnanS USMember ✭✭

    I am facing the same issue in Xamarin forms version 2.0.0.6482.

    https://bugzilla.xamarin.com/show_bug.cgi?id=28277#c6

    Is there any workaround to resolve.

  • RaymondKellyRaymondKelly USMember ✭✭✭

    @DiegoFrata your solution does not seem to work. When ScrollTo is called, it refires all the OnAppearing events for every item in the list and it eventually crashes (on Android). Are you not seeing this behavior?

  • CristianReyesCristianReyes USMember ✭✭

    @DiegoFrata said:
    @FabioP Okay, I decided to give another try and surprisingly this seems to be working for me. Disabling the animation made a good difference.

        public partial class ConversationPage : BasePage
        {
            private bool _autoScroll = true;
    
            public ConversationPage()
            {
                InitializeComponent();
    
                _listView.ItemAppearing += OnItemAppearing;
                _listView.ItemDisappearing += OnItemDisappearing;
            }
    
            protected ConversationViewModel Model
            { 
                get { return (ConversationViewModel)BindingContext; }
            }
    
            private void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
            {
                if (_autoScroll)
                    _listView.ScrollTo(Model.Messages.Last(), ScrollToPosition.End, false);
            }
    
            private void OnItemDisappearing(object sender, ItemVisibilityEventArgs e)
            {
                if (e.Item == Model.Messages.Last())
                    _autoScroll = false;
            }
        }
    

    Works for me, thanks a lot !

  • RaymondKellyRaymondKelly USMember ✭✭✭

    Has anyone figured out how to get this to work when HasEnevenRows=true? It seems the animation of adding a large row messes up the ScrollTo call and it just does not end up in the right place. And there does not seem to be any way to disable row animations. Thanks.

  • cassionandicassionandi USMember ✭✭

    @CristianReyes said:

    @DiegoFrata said:
    @FabioP Okay, I decided to give another try and surprisingly this seems to be working for me. Disabling the animation made a good difference.

        public partial class ConversationPage : BasePage
        {
            private bool _autoScroll = true;
    
            public ConversationPage()
            {
                InitializeComponent();
    
                _listView.ItemAppearing += OnItemAppearing;
                _listView.ItemDisappearing += OnItemDisappearing;
            }
    
            protected ConversationViewModel Model
            { 
                get { return (ConversationViewModel)BindingContext; }
            }
    
            private void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
            {
                if (_autoScroll)
                    _listView.ScrollTo(Model.Messages.Last(), ScrollToPosition.End, false);
            }
    
            private void OnItemDisappearing(object sender, ItemVisibilityEventArgs e)
            {
                if (e.Item == Model.Messages.Last())
                    _autoScroll = false;
            }
        }
    

    Works for me, thanks a lot !

    Hi!

    This do not works for me 100%. It not scroll automaticaly, but if I start to scroll it quickly scrolls to bottom.

  • serkan_CAKMAKserkan_CAKMAK USMember ✭✭
    edited November 2016

    I have the same issue Xamarin forms XAML MVVM UWP Listview is not work ScrollTo()

  • DarshanSDarshanS USMember ✭✭
    edited July 2017

    @Fable As you said, setting the scroll position to start/center works on both iOS and android. But on iOS only top half of the item would be shown which is better compared to nothing, on Android it's completely fine.

  • SRINATHNANDURISRINATHNANDURI USUniversity ✭✭

    I created a property in my ViewModel ListView MyListView {get;set;} . In the page constructor , after setting the Binding Context to my ViewModel , passed a reference to my ListView ... That way, I can use the ListView.ScrollTo(item) ( after i loaded more items) ..

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    @SRINATHNANDURI said:
    I created a property in my ViewModel ListView MyListView {get;set;} . In the page constructor , after setting the Binding Context to my ViewModel , passed a reference to my ListView ... That way, I can use the ListView.ScrollTo(item) ( after i loaded more items) ..

    Massive violation of MVVM principles. A ViewModel should not depend on, control or even be aware of any views that use it - if there even are any.

  • SRINATHNANDURISRINATHNANDURI USUniversity ✭✭

    I totally agree ... Sometimes, until there is a better solution, you need to find a quick fix and then get back to the problem...

Sign In or Register to comment.