0

I have a simple Xamarin.Forms.ContentPage that displays menu items in a ListView:

<ContentPage x:Class="Mob.Views.Public.MenuPage" ... >
  <ScrollView>
        <ListView ItemsSource="{Binding MenuItems}" ItemTapped="{Binding OnMenuItemTapped}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Key}" />
                    <!-- How to pass the "{Binding Value}" to OnMenuItemTapped? -->
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
  </ScrollView>
</ContentPage>

Code behind:

public class MenuPage : ContentPage
{
    public MenuPage()
    {
        InitializeComponent();
        BindingContext = new MenuViewModel(); 
    }
    private async void OnMenuItemTapped(object sender, ItemTappedEventArgs e)
    {
        await (this.BindingContext as MenuViewModel).OnMenuItemTappedAsync(/* MUST PASS THE VALUE HERE*/);
    }
}

As you can see, the ItemsSource is bound to the MenuItems property of my ViewModel. This property is of type Dictionnary<string, string>. The Key is used to display the text of the items while the Value should be passed as a parameter to OnMenuItemTapped event.

class MenuViewModel : ViewModelBase
{
    ...
    public IDictionary<string, string> MenuItems { get { return _menuItems; } set { SetProperty(ref _menuItems, value); } }
    // public ICommand OnMenuItemTappedCommand { get; set; }
    public MenuViewModel()
    {
        MenuItems = new Dictionary<string, string>();
        MenuItems.Add("XXX", "PageX");
        MenuItems.Add("YYY", "PageY");
        MenuItems.Add("ZZZ", "PageZ");
        // ...
        // I would've prefere to bind the item tap using a command but I can't figure out how to
        // OnMenuItemTappedCommand = new Command<string>(OnMenuItemTappedAsync);
    }

    public async Task OnMenuItemTappedAsync(string targetPage)
    {
        // await Navigation.PushModalAsync(...);
        // --> depending on the targetPage
    }
}

My goal is to navigate to the right page depending on the value passed to OnMenuItemTappedAsync.

Note, I am trying to do "pure" MVVM here. Meaning I know that I should not use events and leave the code behind almost empty. But I can't figure out how to use commands in this context.

Any idea/advice how to achieve this?

TaiT's
  • 3,138
  • 3
  • 15
  • 26
  • 1
    I believe that e.Item will give you the databound item from the list, from which you can get both the Key and the Value – Jason Apr 05 '17 at 21:20
  • @Jason: Thank you very much! It seems so obvious now by the way...! I still have a doubt if it's possible to "easily" map commands directly in any way, but this will do it for sure. Thanks again for the fast feedback :)! – TaiT's Apr 05 '17 at 21:46
  • A bit offtopic: Not sure if you put Listview into ScrollView just for this demo, otherwise please have a look here https://stackoverflow.com/questions/6210895/listview-inside-scrollview-is-not-scrolling-on-android/6211286#6211286 – K232 Sep 17 '17 at 13:26

1 Answers1

1

Add a TapGesture to ViewCell content and bind the Command with it. Ex:

<TapGestureRecognizer Command="{Binding OnMenuItemTappedCommand}" CommandParameter="{Binding .}" />

In your case you can Bind Command directly to the TextCell.

<TextCell Command="{Binding OnMenuItemTappedCommand}" CommandParameter="{Binding .}">
Dilmah
  • 1,137
  • 11
  • 14