“TouchBehavior.CommandParameter”和“TouchBehavior.LongPressCommandParameter”始终作为“null”传递给“Command”和“LongPressCommand”

问题描述 投票:0回答:1

TouchBehavior.CommandParameter
TouchBehavior.LongPressCommandParameter
始终作为
null
传递到
Command
LongPressCommand

在以下示例中,当点击

CollectionView
中的项目时,生成的警报将始终显示
Selected value:
,因为 CommandParameter 始终为
null
。例如,当用户点击
Selected vale: Item 1
时,它应该显示
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");
}

样本复制

以下是此错误的重现示例的链接:https://github.com/hansmbakker/bugrepro-communitytoolkit-maui-touchbehavior-parameter

c# .net xaml maui maui-community-toolkit
1个回答
0
投票

说明

在 .NET MAUI 中,您需要为每个

BindingContext
手动设置
Behavior
。换句话说,行为不会继承它们所附加的
BindingContext
VisualElement

来源: https://learn.microsoft.com/dotnet/maui/fundamentals/behaviors?view=net-maui-8.0#create-a-net-maui-behavior

image

更新代码

这里是更新的 XAML,可以让您的代码正常运行。它使用视图到视图绑定将

TouchBehavior.BindingContext
绑定到
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>

与Behavior BindingContext问题有点无关,这是我对ViewModel进行小幅性能改进的建议(

Title
Items
都可以是只读属性):

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

更新后的应用程序截图

这是更新代码后应用程序按预期工作的屏幕截图:

.NET MAUI 社区工具包单元测试

这是我为

TouchBehavior
中的
CommunityToolkit.Maui
编写的单元测试,我们验证
LongPressCommand
确实通过了
LongPressCommandParameter

https://github.com/CommunityToolkit/Maui/blob/51dc63a7642370849e413d87072b668fa022e303/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs#L612-L674

这是我为

TouchBehavior
中的
CommunityToolkit.Maui
编写的单元测试,我们验证
Command
确实通过了
CommandParameter

https://github.com/CommunityToolkit/Maui/blob/51dc63a7642370849e413d87072b668fa022e303/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs#L550-L610

© www.soinside.com 2019 - 2024. All rights reserved.