CommandParameters中的ContextMenu在WPFCommandParameters、ContextMenu、WPF

2023-09-07 09:54:28 作者:酒巷清风

我有一种情况,我有一个WPF TreeView控件,有一个 HierarchicalDataTemplate 为它的项目。现在在 HierarchicalDataTemplate ,我有一个标签标签有一个文本菜单与菜单项的删除。该删除菜单项被绑定到一个名为命令的DeleteCommand 这是已经被设置为数据类型类的一部分 HierarchicalDataTemplate

I have a scenario where I have a WPF TreeView control that has an HierarchicalDataTemplate for its items. Now inside the HierarchicalDataTemplate, I have a Label and the Label has a ContextMenu with a menuitem for Delete. The Delete menuitem is bound to a Command called DeleteCommand which is a part of the class that has been set as the DataType of the HierarchicalDataTemplate.

现在,我要传递的 CommandParameters 的TreeView 控制文本菜单的删除菜单项的的DeleteCommand ,这样我可以处理删除当前所选项目的TreeViewItems的选择。

Now, I want to pass the TreeView control in the CommandParameters of the ContextMenu's Delete menuitem's DeleteCommand so that I can handle the selection of the TreeViewItems on the deletion of the currently selected item.

但是,如果我绑定 CommandParameters {绑定的ElementName = TreeViewName} 或任何与此有关的,它总是空,除非绑定元素是一个属性的DataContext

But if I bind the CommandParameters as the {Binding ElementName=TreeViewName} or whatever for that matter, it is always null unless the binded element is a property in the DataContext.

任何人都可以帮我一个解决方案,因为我觉得,我已经尝试了所有可能的事情,如的RelativeSource和AncestorType等,但它总是空。对我来说,它看起来像任何一个限制,或在框架中的一个错误。

Can anyone help me with a solution because I think, I have tried all the possible things such as RelativeSource and AncestorType etc but its always null. To me, it looks like either a limitation or a bug in the framework.

推荐答案

现在的问题是,该文本菜单是在其自己的视觉树的根,所以任何RelativeSource.FindAncestor绑定不会走过去的文本菜单。

The problem is that the ContextMenu is at the root of its own visual tree, so any RelativeSource.FindAncestor bindings won't go past the ContextMenu.

一种解决方案是使用PlacementTarget属性设置一个二阶段从你的标签绑定:

One solution is to use the PlacementTarget property to set up a two-stage binding from your Label:

<Label Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={
    x:Type TreeView}}}">
    <Label.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Delete" Command="{x:Static local:Commands.DeleteCommand}"
                CommandParameter="{Binding PlacementTarget.Tag, RelativeSource={
                RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
        </ContextMenu>
    </Label.ContextMenu>
</Label>

这是相当哈克,但是。你最好设置CommandTarget你的菜单项的文本菜单的PlacementTarget的财产,有您的TreeView的命令处理程序。这意味着你将不必通过周围的树视图。

This is quite hacky, however. You're better off setting the CommandTarget property of your MenuItem to the ContextMenu's PlacementTarget and having the command handler on your TreeView. This means you won't have to pass the TreeView around.