我有一个用于ItemsControl的数据模板的自定义控件。我想在每个项目上放置一个ContextMenu,让它调用UserControl的View Model来处理命令。使用下面的XAML,我可以在自定义控件上获取单击事件,以在用户控件视图模型中调用SelectedItemCommand。但是,使用上下文菜单的类似语法失败。默认情况下,我会为每个自定义控件获取视图模式。我使用的任何RelativeSource语法值都不会解析为用户控件的视图模型(RelativeSource Self)。
什么是神奇的代码?
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:MyCustomItem Width="Auto"
Command="{Binding DataContext.SelectedItemCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding}">
<controls:MyCustomItem.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
Header="Clear All" />
</ContextMenu>
</controls:MyCustomItem.ContextMenu>
</controls:MyCustomItem>
</DataTemplate>
</ItemsControl.ItemTemplate>
答案 0 :(得分:10)
ContextMenu doesn't lie in same Visual Tree
与ItemsControl相同。因此,RelativeSource和ElementName在Binding中不起作用,因为它们遍历Visual树以找到源。
如果您使用的是WPF 4.0或更高版本,则可以使用 x:Reference
标记扩展名与ItemsControl dataContext绑定。
在ItemsControl上设置x:Name
并使用x:Reference
进行绑定,如下所示:
<ItemsControl x:Name="itemsControl">
....
<MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
Source={x:Reference itemsControl}}"
Header="Clear All" />
....
</ItemControl>
如果您定位的版本低于WPF 4.0,也可以使用 Freezable BindingProxy
方法。有关该方法,请参阅我对here的回答。