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.