【wpf】数据模板 + ContextMenu 导致的命令 绑定失效
背景
测试环境 .net6 wpf
TreeView 中我写了一个数据模板,数据模板的StackPanel 中,我加了一个ContextMenu右键菜单。
<TreeView ItemsSource="{Binding Path=WorkflowViewToolsTree}">
<TreeView.ItemTemplate>
<!--子项的绑定-->
<HierarchicalDataTemplate DataType="{x:Type local_md:ToolsNodeItem}" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal" Background="Transparent">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="删除" Command="{Binding MenuItemCmd, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" CommandParameter="123"/>
<MenuItem Header="上移" Command="{Binding MenuItemCmd}" CommandParameter="123"/>
<MenuItem Header="下移" Command="{Binding Path=DataContext.MenuItemCmd, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl,AncestorLevel=4}}" CommandParameter="123"/>
<!--<MenuItem Header="{Binding Path=Name, Source={x:Reference Name}}"/>-->
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="{Binding Icon}" Width="20" Margin="0,0,10,0"/>
<TextBlock Text="{Binding DisplayName}" VerticalAlignment="Center"/>
<StackPanel.ToolTip>
<TextBlock Text="{Binding TypeName}"/>
</StackPanel.ToolTip>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
结果 ContextMenu一切绑定都无效了,RelativeSource各种找都没有用!
一开始以为是模板导致的,但模板中其他元素的绑定都是OK的,说明应该不是模板的问题。于是我开始怀疑是ContextMenu的问题。
有的文章说:ContextMenu是一个独立的窗口不在可视化树中,所以向上找不到。
于是我在一个其他元素中写了ContextMenu,发现一切正常:
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="删除" Command="{Binding MenuItemCmd}" CommandParameter="123"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
解决方案
使用x:Reference
<MenuItem Header="删除" Command="{Binding Path=DataContext.MenuItemCmd, Source={x:Reference Name=top_uc}}" CommandParameter="删除"/>
<MenuItem Header="上移" Command="{Binding Path=DataContext.MenuItemCmd, Source={x:Reference Name=top_uc}}" CommandParameter="上移"/>
<MenuItem Header="下移" Command="{Binding Path=DataContext.MenuItemCmd, Source={x:Reference Name=top_uc}}" CommandParameter="下移"/>
这里有个解决方法是通过 x:Reference 指定绑定对象的Name(代码中的 top_uc 是我给被绑定控件取的名字),然后明确的指定Path。如果绑定的内容在DataContext里面,这个DataContext是不能丢的,一定要写上!
小结
目前的判断是 Command 绑定的特殊性,如果Command 处于数据模板之内,就必须写全。
<MenuItem Header="下移2" Command="{Binding Path=DataContext.MenuItemCmd, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
如果Command即在模板里,还在ContextMenu里。那就必须使用x:Reference 了
结束
目前只是看到现象,如果哪位大佬知道具体原因,请和我在评论区探讨,感谢!
最后,强调一下,我是在 .net6 wpf 下做的测试,其他环境可能表现不一样。
作者:宋桓公
出处:http://www.cnblogs.com/douzi2/
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。