Xamarin: How to go to bottom of ListView using MVVM pattern?

82 Views Asked by At

Is there a way to go to the bottom of ListView using the MVVM pattern? I do that using codebehind, but I'd like to do it using MVVM, if possible.

I use the ScrollTo() method of ListView.

Thanks

1

There are 1 best solutions below

0
Julian On

One way to do this is to attach a delegate method to your ViewModel and invoke the delegate. Another approach would be to use an event handler. You can also subscribe to the CollectionChanged event if you use an ObservableCollection. With either approach you're not breaking the MVVM pattern, because you're applying inversion of control.

Note that in MVVM the ViewModel must not know anything about Views, therefore it also cannot know that the ScrollTo() method even exists. That said, you won't get around calling the ScrollTo() method from within your View's code-behind.

Solution using delegate

ViewModel

In your ViewModel, add and call a delegate like so:

public class MyViewModel : INotifyPropertyChanged
{
    public ObservableCollection<string> ListItems = new ObservableCollection<string>();

    // delegate
    public delegate void SomethingHappenedDelegate(string item);
    public SomethingHappenedDelegate SomethingHappened = null;

    private ICommand _someCommand;
    public ICommand SomeCommand => _someCommand ??= new Command(SomeMethod);

    private void SomeMethod()
    {
        var newItem = "hello";
        ListItems?.Add(newItem);
        SomethingHappened?.Invoke(newItem);
    }

    // skipping other stuff like initialization, INotifyPropertyChanged implementation, etc.
}

View

Then, in your View's code behind, you can set the delegate:

public partial class MyPage : ContentPage
{
    public MyPage(MyViewModel viewModel)
    {
        InitializeComponent();
        viewModel.SomethingHappened = ScrollToBottom;
        BindingContext = viewModel;
    }

    private void ScrollToBottom(string item)
    {
        MyListView.ScrollTo(item, ScrollToPosition.End, true);
    }
}

In your View's XAML, you bind to the command:

<StackLayout>
    <Button
      Text="Add item and scroll"
      Command="{Binding SomeCommand}" />

    <ListView
      x:Name="MyListView"
      ItemsSource="{Binding ListItems}" />
</StackLayout>

You could just as well implement your own event and subscribe to that or use the built-in events of the ObservableCollection. That's up to you, but the underlying concept would be the same. You cannot get around having the call to ScrollTo() live somewhere in your View`s code behind without breaking MVVM.