Both TouchBehavior.CommandParameter
and TouchBehavior.LongPressCommandParameter
are always passed as null
to Command
and LongPressCommand
.
In the following example, when an item in the CollectionView
is tapped, the resulting alert will always display Selected value:
because the CommandParameter is always null
. It should say Selected vale: Item 1
, for example, when the user taps Item 1
.
<VerticalStackLayout Padding="30,0"
Spacing="25">
<Label Text="{Binding Title}"
Style="{StaticResource Headline}"
SemanticProperties.HeadingLevel="Level1" />
<Label Text="Tapping or long pressing an item does not correctly pass that item as CommandParameter or LongTouchCommandParameter."
Style="{StaticResource SubHeadline}"
SemanticProperties.HeadingLevel="Level1" />
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type x:String}">
<Label Padding="10"
Text="{Binding .}"
x:Name="Label">
<Label.Behaviors>
<toolkit:TouchBehavior Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.ShowItemCommand}"
CommandParameter="{Binding .}"
LongPressCommand="{Binding Source={x:Reference collectionView}, Path=BindingContext.ShowItemCommand}"
LongPressCommandParameter="{Binding .}"
<!--
CommandParameter and LongPressCommandParameter are always passed as null in the CommunityToolkit.Maui TouchBehavior.
this was not the case with https://github.com/Axemasta/Maui.TouchEffect -->
</Label.Behaviors>
</Label>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
public partial class MainViewModel : ObservableObject
{
public string Title => "Hello, Maui!";
public ObservableCollection<string> Items { get; set; } = ["Item 1", "Item 2", "Item 3"];
/// <summary>
/// item is always null. This was not the case in https://github.com/Axemasta/Maui.TouchEffect
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
[RelayCommand]
private Task ShowItem(string item) => Application.Current.MainPage.DisplayAlert($"Selected value:", item, "OK");
}
Here is a link to a reproduction sample for this bug: https://github.com/hansmbakker/bugrepro-communitytoolkit-maui-touchbehavior-parameter
In .NET MAUI, you are required to manually set the BindingContext
for every Behavior
. In other words, Behaviors do not inherit the BindingContext
of the VisualElement
to which they are attached.
Here is the updated XAML to get your code working. It uses a view-to-view binding to bind TouchBehavior.BindingContext
to Label.BindingContext
:
<VerticalStackLayout Padding="30,0"
Spacing="25">
<Label Text="{Binding Title}"
Style="{StaticResource Headline}"
SemanticProperties.HeadingLevel="Level1" />
<Label Text="Tapping or long pressing an item does not correctly pass that item as CommandParameter or LongTouchCommandParameter."
Style="{StaticResource SubHeadline}"
SemanticProperties.HeadingLevel="Level1" />
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type x:String}">
<Label Padding="10"
Text="{Binding .}"
x:Name="label">
<Label.Behaviors>
<toolkit:TouchBehavior Command="{Binding Source={x:Reference collectionView}, Path=BindingContext.ShowItemCommand}"
CommandParameter="{Binding .}"
LongPressCommand="{Binding Source={x:Reference collectionView}, Path=BindingContext.ShowItemCommand}"
LongPressCommandParameter="{Binding .}"
BindingContext="{Binding Source={x:Reference label}, Path=BindingContext}"/>
</Label.Behaviors>
</Label>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
A bit unrelated to the Behavior BindingContext problem, here is my recommendation for small performance improvement to your ViewModel (both Title
and Items
can be read-only properties):
public partial class MainViewModel : ObservableObject
{
public string Title { get; } = "Hello, Maui!";
public ObservableCollection<string> Items { get; } = ["Item 1", "Item 2", "Item 3"];
[RelayCommand]
private Task ShowItem(string item) => Application.Current.MainPage.DisplayAlert($"Selected value:", item, "OK");
}
Here is a screen shot of your app working as expected after updating the code:
Here are the Unit Tests I wrote for the TouchBehavior
in CommunityToolkit.Maui
where we verify the LongPressCommand
does indeed pass in LongPressCommandParameter
;
And here are the Unit Tests I wrote for the TouchBehavior
in CommunityToolkit.Maui
where we verify the Command
does indeed pass in CommandParameter
;