redar ismail
redar ismail

Reputation: 171

Xamarin ListView itemSelected MVVM

I am very new to Xamarin.Form, I would appreciate your help.

I am using MVVM pattern for my current project. I have listview populated with people, I want to select the item in list view and show the detail. Unfortunately, I could not find any example addressing this issue.

This is my Bindable Class :

public static readonly BindableProperty CommandProperty =
BindableProperty.Create(
      propertyName: "Command",
      returnType: typeof(ICommand),
      declaringType: typeof(ListViewItemSelected));

public ICommand Command
{
    get { return (ICommand)GetValue(CommandProperty); }
    set { SetValue(CommandProperty, value); }
}

protected override void OnAttachedTo(ListView bindable)
{
    base.OnAttachedTo(bindable);

    bindable.ItemSelected += BindableOnItemSelected;
    bindable.BindingContextChanged += BindableOnBindingContextChanged;
}

private void BindableOnBindingContextChanged(object sender, EventArgs e)
{
    var lv = sender as ListView;
    BindingContext = lv?.BindingContext;
}

private void BindableOnItemSelected(object sender, SelectedItemChangedEventArgs e)
{

    if (Command == null)
        return;
    Command.Execute(null);
}

I am not sure about the next step in my ViewModel. I created ICommand Property to exacute the method

public ICommand DetailView { get; set; }

In my constructor i added

DetailView = new Command(PathToDetailView);

I created this method

void PathToDetailView()
{
     //Which I do not know what should go here to redirect to DetailsPage for each item.
}

I am kind of stuck in the DetailViewPage how to get the value.

I appreciate your help.

Upvotes: 1

Views: 2697

Answers (1)

Paul Kertscher
Paul Kertscher

Reputation: 9742

You have several options here, but the easiest may be to bind the SelectedItem of your ListView to a property in your viewmodel

public Person SelectedPerson
{
  get => _selectedPerson;
  set
  {
    if(_selectedPerson == value)
    {
      return;
    }
    _selectedPerson = value;
    OnPropertyChanged();
  }
}

protected void OnPropertyChanged([CallerMemberName] propertyName = null)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

I've made use of INotifyPropertyChanged and CallerMemberNameAttribute. INotifyPropertyChanged will inform your view (or rather your BindableProperty), that a property in your viewmodel has changed and gives the view the opportunity to update the contents. CallerMemberNameAttribute is syntactic sugar, that lets you omit the name of the property you are calling OnPropertyChangedFrom. It's basically the same as if you called

OnPropertyChanged(nameof(SelectedPerson));

In your view, you can now bind the ListView to SelectedPerson

<ListView ... SelectedItem="{Binding SelectedPerson}">...</ListView>

and use SelectedPerson in PathToDetailView.

Upvotes: 1

Related Questions