使用多个模板时,将命令绑定到 `ContextMenu` 中的 `DataTemplate`?
Bind command to `DataTemplate` in `ContextMenu` when using multiple templates?
我正在尝试提供具有不同外观和功能的上下文菜单项,但我找不到将命令绑定到这些项的方法。每个菜单项的视图模型都派生自一个 class AbstractEntryViewModel
。这是我当前项目结构的一个简短示例。使用 ContextMenu.Resources
是我发现将模板绑定到特定类型的唯一方法。
<ContextMenu ItemsSource="{Binding Entries}">
<ContextMenu.Resources>
<DataTemplate DataType="{x:Type local:NopEntryViewModel}">
<!-- Content -->
</DataTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:GroupEntryViewModel}"
ItemsSource="{Binding Entries}">
<!-- Content -->
</HierarchicalDataTemplate>
<!-- More templates -->
</ContextMenu.Resources>
</ContextMenu>
internal abstract AbstractEntryViewModel : INotifyPropertyChanged {
public abstract void Invoke ();
// ...
}
internal NopEntryViewModel : AbstractEntryViewModel {
public override void Invoke () {}
}
internal GroupEntryViewModel : AbstractEntryViewModel {
public override void Invoke () { /* ... */ }
// ...
}
// More view models
通常我可以像这样将命令绑定到 MenuItem
<MenuItem Command="{Binding StaticResourceOrViewModelProperty}" />
如何使用数据模板做同样的事情?是否有一个不可见的容器,一个数据模板内容的包装器,我可以用它来绑定命令?
为简单起见,假设有 2 个派生的 ViewModel,VM1
和 VM2
,分别有一个 Command
Command1
和一个 Command2
。
两步:
1) 在基础ViewModel
中定义这个属性:
public Type Type
{
get { return GetType(); }
}
我们不能直接使用 GetType()
,我们需要包装 属性 因为 WPF Bindings
只能使用属性。
2) 使用此 属性 在 Style
上为 ContextMenu
MenuItem
:
设置一个 DataTrigger
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM1}">
<Setter Property="Command" Value="{Binding Command1}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM2}">
<Setter Property="Command" Value="{Binding Command2}"/>
</DataTrigger>
<!-- add other DataTriggers, one for every ViewModel -->
</Style.Triggers>
</Style>
</ContextMenu.Resources>
DataTemplates
与您一样设置,其中:
<DataTemplate DataType="{x:Type local:VM1}">
<!-- Content -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- Content -->
</DataTemplate>
我正在尝试提供具有不同外观和功能的上下文菜单项,但我找不到将命令绑定到这些项的方法。每个菜单项的视图模型都派生自一个 class AbstractEntryViewModel
。这是我当前项目结构的一个简短示例。使用 ContextMenu.Resources
是我发现将模板绑定到特定类型的唯一方法。
<ContextMenu ItemsSource="{Binding Entries}">
<ContextMenu.Resources>
<DataTemplate DataType="{x:Type local:NopEntryViewModel}">
<!-- Content -->
</DataTemplate>
<HierarchicalDataTemplate
DataType="{x:Type local:GroupEntryViewModel}"
ItemsSource="{Binding Entries}">
<!-- Content -->
</HierarchicalDataTemplate>
<!-- More templates -->
</ContextMenu.Resources>
</ContextMenu>
internal abstract AbstractEntryViewModel : INotifyPropertyChanged {
public abstract void Invoke ();
// ...
}
internal NopEntryViewModel : AbstractEntryViewModel {
public override void Invoke () {}
}
internal GroupEntryViewModel : AbstractEntryViewModel {
public override void Invoke () { /* ... */ }
// ...
}
// More view models
通常我可以像这样将命令绑定到 MenuItem
<MenuItem Command="{Binding StaticResourceOrViewModelProperty}" />
如何使用数据模板做同样的事情?是否有一个不可见的容器,一个数据模板内容的包装器,我可以用它来绑定命令?
为简单起见,假设有 2 个派生的 ViewModel,VM1
和 VM2
,分别有一个 Command
Command1
和一个 Command2
。
两步:
1) 在基础ViewModel
中定义这个属性:
public Type Type
{
get { return GetType(); }
}
我们不能直接使用 GetType()
,我们需要包装 属性 因为 WPF Bindings
只能使用属性。
2) 使用此 属性 在 Style
上为 ContextMenu
MenuItem
:
DataTrigger
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM1}">
<Setter Property="Command" Value="{Binding Command1}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM2}">
<Setter Property="Command" Value="{Binding Command2}"/>
</DataTrigger>
<!-- add other DataTriggers, one for every ViewModel -->
</Style.Triggers>
</Style>
</ContextMenu.Resources>
DataTemplates
与您一样设置,其中:
<DataTemplate DataType="{x:Type local:VM1}">
<!-- Content -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:VM2}">
<!-- Content -->
</DataTemplate>