如何在DataTemplate内通过x:Bind绑定ViewModel的IAsyncRelayCommand命令?
问题原因
DataTemplate 中指定了x:DataType="model:ObservableProjectItem"时,x:Bind的默认作用域被限制为ObservableProjectItem类型,因此直接写ViewModel.AddProjectItemCommand会在当前项的属性里查找,自然找不到页面根层级的ViewModel。
前置修正
首先需要把页面后台的ViewModel从字段改成属性,绑定系统仅支持绑定属性,不支持绑定字段:
public sealed partial class BuildingView : Page { public BuildingView() { this.InitializeComponent(); } // 改为带get访问器的属性 internal BuildingViewModel ViewModel { get; } = Ioc.Default.GetService<BuildingViewModel>(); }
解决方案
方案1:使用ElementName绑定(兼容性最好,所有UWP/WinUI版本都可用)
- 给你的Page根节点添加
x:Name属性:
<Page x:Class="你的项目命名空间.BuildingView" x:Name="PageRoot" <!-- 保留原有其他属性 --> >
- 修改MenuFlyoutItem的Command绑定:
<MenuFlyoutItem Command="{Binding ElementName=PageRoot, Path=ViewModel.AddProjectItemCommand}" <!-- 如果需要传递当前点击的项目作为命令参数,添加下面这行 --> CommandParameter="{x:Bind}" Text="添加项目" Icon="Add" />
方案2:使用RelativeSource查找父级页面
不需要给页面加名称,直接通过父级类型匹配绑定:
<MenuFlyoutItem Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Page}, Path=ViewModel.AddProjectItemCommand}" />
方案3:WinUI 3 1.4+版本使用x:Bind绑定
如果你的项目是WinUI 3 1.4及以上版本,x:Bind已经支持ElementName,可以直接写:
<MenuFlyoutItem Command="{x:Bind ViewModel.AddProjectItemCommand, ElementName=PageRoot}" />
内容的提问来源于stack exchange,提问作者Brecons
相关产品推荐
相关产品推荐

