简体   繁体   中英

.NET MAUI 7 - ListView MenuItem CommandParameter not binded correctly

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; }
    }
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM