【问题标题】:.NET Maui SwipeItem command binding to viewmodel ancestor fails.NET Maui SwipeItem 命令绑定到视图模型祖先失败
【发布时间】:2023-02-14 06:40:45
【问题描述】:

我有以下 XAML

<CollectionView.ItemTemplate>
    <DataTemplate x:DataType="model:LogEntry">
        <SwipeView>
            <SwipeView.RightItems>
                <SwipeItem Text="Delete"
                           BackgroundColor="Orange"
                           Command="{Binding Source={RelativeSource AncestorType={x:Type viewModel:MainPageViewModel}}, Path=RemoveLogEntryCommand}"
                           CommandParameter="{Binding .}" />
                <SwipeItem Text="Delete" 
                           BackgroundColor="Red"
                           IsDestructive="True" />
            </SwipeView.RightItems>
            <Grid Padding="10">
                <Frame HeightRequest="125"
                           Padding="0"
                           Style="{StaticResource CardView}">
                    <Frame.GestureRecognizers>
                        <TapGestureRecognizer CommandParameter="{Binding .}"
                                              Command="{Binding Source={RelativeSource AncestorType={x:Type viewModel:MainPageViewModel}}, Path=GotoLogEntryDetailsCommand}" />
                    </Frame.GestureRecognizers>
                    <Grid Padding="0"
                              ColumnDefinitions="80,*">

使用社区工具包的以下 ICommand 声明

[RelayCommand]
private async Task GotoLogEntryDetails(LogEntry logEntry)
{
    if (logEntry == null)
        return;

    await _appNavigationService.GoTo($"{nameof(LogEntryDetailsPage)}", true,
        new Dictionary<string, object>
        {
            { "LogEntry", logEntry }
        });


}

[RelayCommand]
private async Task RemoveLogEntry(LogEntry logEntry)
{

}

如果我在 RemoveLogEntry 中放置一个断点,然后单击我的删除按钮,则永远不会到达断点。如果我将 RemoveLogEntry 放在点击手势上并点击我的项目,然后到达断点,所以我知道代码生成器已经创建了一个有效的 ICommand。

Intellisense 告诉我CommandParameter . 上的参数实际上是一个 LogEntry,因此我需要声明 viewModel 类型。

SwipeItem 的祖先绑定路径有什么问题?

【问题讨论】:

    标签: .net-maui xaml-binding


    【解决方案1】:

    更新

    这个答案的第一部分(“Views vs Viewmodels”)可能是错误的。我在好几个地方都看到过这种“viewmodel reference”语法。还没有花时间测试它是如何/何时工作的。


    视图与视图模型

    UI 元素(视图)和视图模型处于不同的层次结构中。视图模型永远不是视图的祖先。所以你找不到这样的祖先。

    相反,找到作为祖先的 VIEW。该视图的BindingContext 将是相应的视图模型。

    改变:

    <SwipeItem ... Command="{Binding Source={RelativeSource AncestorType={x:Type viewModel:MainPageViewModel}}, Path=RemoveLogEntryCommand}"
    

    到:

    <SwipeItem ... Command="{Binding Source={RelativeSource AncestorType={x:Type MainPageView}}, Path=BindingContext.RemoveLogEntryCommand}"
    

    替代语法

    但是,我从不使用该语法。我发现为我要引用的元素提供 x:Name 更容易。然后可以使用一个简单的x:Reference来源:

    <ContentPage
      ...
      x:Name="thisPage">
        ...
        <SwipeItem ... Command={Binding BindingContext.RemoveLogEntryCommand, Source={x:Reference thisPage}"
    

    【讨论】:

    • 太感谢了,辛苦了我什至无法使用我开始使用的语法计算出建议所需的命名空间。只是不断收到构建错误“无法解析类型”Lofty.Logbook.Views:MainPage“无论我尝试什么,但使用参考工作正常。再次感谢。
    • 因此,关于这一切让我感到困扰的一件事是,新来者如何在不来到这里或不深入了解 XAML 引擎源代码的情况下甚至找出这些关系来提出绑定路径?是否有合适的文档来源来解释它?我遵循了 James Montemagmo 的视频指南,他只是使用了我原来的东西。从来没有显示点击他的删除按钮击中断点,但我认为处于他的位置的人显示的是正确的。
    • 你确定那正是他所拥有的吗?他是专家,但 AFAIK 在 xaml 中引用视图模型祖先在任何情况下都无法工作。将这些微妙之处拼凑起来是一项艰巨的任务。开始重新文档的一个地方是Data Binding,它指向各种链接和示例。包括Relative Binding。另见github.com/xamarin/xamarin-forms-samples/tree/main/…
    猜你喜欢
    • 2022-01-09
    • 2023-01-14
    • 1970-01-01
    • 2012-10-02
    • 2017-07-10
    • 2023-01-11
    • 2022-10-24
    • 2022-01-17
    • 2014-11-08
    相关资源
    最近更新 更多