Home > other >  .NET MAUI 7 - ListView MenuItem CommandParameter not binded correctly
.NET MAUI 7 - ListView MenuItem CommandParameter not binded correctly

Time:12-17

My problem is similar as this one MenuItem CommandParameter = null ! Why?

The CommandParameter="{Binding .}" in my MenuItem, nested in ViewCell.ContextActions is always null when I read it. I also tried CommandParameter="{Binding}".

Here is the full code:

View

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:viewmodel="clr-namespace:CookUs.ViewModel"
         xmlns:model="clr-namespace:CookUs.Model"
         x:Class="CookUs.View.ViewRecipePage"
         x:DataType="viewmodel:ViewRecipeViewModel"
         Title="{Binding Recipe.Name}">

<ScrollView>
    <VerticalStackLayout>
        <ListView ItemsSource="{Binding Recipe.Ingredients}" 
                  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.ContextActions>
                            <MenuItem Text="Add to Cart" IconImageSource="add_to_cart.png"
                                      Command="{Binding Source={x:Reference listView}, Path=BindingContext.AddToCartCommand}"
                                      CommandParameter="{Binding .}" />
                        </ViewCell.ContextActions>
                        <StackLayout x:DataType="model:Ingredient">
                            <Label Text="{Binding Name}" FontAttributes="Bold" FontSize="Small" HorizontalTextAlignment="Center"/>
                            <Label Text="{Binding Quantity}" FontSize="Micro" HorizontalTextAlignment="Center"/>
                        </StackLayout>

                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </VerticalStackLayout>
</ScrollView>

ViewModel

public Command AddToCartCommand { get; }

public ViewRecipeViewModel()
{
    AddToCartCommand = new Command(OnAddToCartAsync);
}

private async void OnAddToCartAsync(object obj)
{
        
if (obj == null) return;
Ingredient i = obj as Ingredient;
if(!(await DataStore.AddToCartAsync(i))) {
    await Application.Current.MainPage.DisplayAlert("Error", "Failed to add to cart", "OK");
}
OnPropertyChanged(nameof(Cart));  
}

Model

namespace CookUs.Model
{
    public class Ingredient
    {
        public string Name { get; set; }
        public string Quantity { get; set; }
    }
}

CodePudding user response:

Update

Your problem is the x:DataType. When using Compiled Bindings, you need to set the correct DataType everywhere where the BindingContext changes. In this case, you'll need to add the x:DataType="Ingredient" on the DataTemplate instead of the StackLayout:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:viewmodel="clr-namespace:CookUs.ViewModel"
         xmlns:model="clr-namespace:CookUs.Model"
         x:Class="CookUs.View.ViewRecipePage"
         x:DataType="viewmodel:ViewRecipeViewModel"
         Title="{Binding Recipe.Name}">

<ScrollView>
    <VerticalStackLayout>
        <ListView ItemsSource="{Binding Recipe.Ingredients}" 
                  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate
                    x:DataType="model:Ingredient">
                    <ViewCell>
                        <ViewCell.ContextActions>
                            <MenuItem Text="Add to Cart" IconImageSource="add_to_cart.png"
                                      Command="{Binding Source={x:Reference listView}, Path=BindingContext.AddToCartCommand}"
                                      CommandParameter="{Binding .}" />
                        </ViewCell.ContextActions>
                        <StackLayout>
                            <Label Text="{Binding Name}" FontAttributes="Bold" FontSize="Small" HorizontalTextAlignment="Center"/>
                            <Label Text="{Binding Quantity}" FontSize="Micro" HorizontalTextAlignment="Center"/>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </VerticalStackLayout>
</ScrollView>

From previous version of the answer:

Notice the . that is part of the binding:

CommandParameter="{Binding .}"

It means to pass the entire item as a parameter.

  • Related