【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 下做的测试,其他环境可能表现不一样。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code bean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值