C# WPF 中 ContextMenu 中的 CommandParameters

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/504533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:55:59  来源:igfitidea点击:

CommandParameters in ContextMenu in WPF

c#wpf.net-3.5

提问by

I have a scenario where I have a WPF TreeView control that has an HierarchicalDataTemplatefor its items. Now inside the HierarchicalDataTemplate, I have a Labeland the Labelhas a ContextMenuwith a menuitem for Delete. The Delete menuitem is bound to a Command called DeleteCommandwhich is a part of the class that has been set as the DataTypeof the HierarchicalDataTemplate.

我有一个场景,我有一个 WPF TreeView 控件,HierarchicalDataTemplate它的项目有一个。现在里面的HierarchicalDataTemplate,我有一个LabelLabel具有ContextMenu与一个菜单项Delete。该删除菜单项被绑定到一个命令调用DeleteCommand这是一个已经被设定为一个类的一部分DataTypeHierarchicalDataTemplate

Now, I want to pass the TreeViewcontrol in the CommandParametersof the ContextMenu's Deletemenuitem's DeleteCommandso that I can handle the selection of the TreeViewItems on the deletion of the currently selected item.

现在,我想在 ContextMenu 的menuitem 中传递TreeView控件,以便我可以在删除当前选定的项目时处理 TreeViewItems 的选择。CommandParametersDeleteDeleteCommand

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

但是,如果我将 theCommandParameters作为 the{Binding ElementName=TreeViewName}或其他任何内容进行绑定,则它始终为 null,除非绑定的元素是DataContext.

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 和 AncestorType 等,但它始终为空。对我来说,它看起来像是框架中的限制或错误。

回答by Szymon Rozga

Take a look at WPF CommandParameter Binding Problem. Maybe it can provide some pointers as to what's going on.

看看WPF 命令参数绑定问题。也许它可以提供一些关于正在发生的事情的指示。

回答by Robert Macnee

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.

问题是 ContextMenu 位于其自己的可视化树的根部,因此任何 RelativeSource.FindAncestor 绑定都不会经过 ContextMenu。

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

一种解决方案是使用PlacementTarget属性从您的 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>

This is quite hacky, however. You're better off setting the CommandTargetproperty 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.

然而,这很hacky。最好将 MenuItem的CommandTarget属性设置为ContextMenu 的 PlacementTarget 并在 TreeView 上设置命令处理程序。这意味着您不必传递 TreeView。

回答by user714307

<MenuItem Header="..." 
          Command="{Binding Path=...}" 
          CommandParameter="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type ContextMenu}}}">
</MenuItem>

ContextMenu.PlacementTarget, is Label, where the menuitem is hosted. From Lavel, its parent Treeview is accessable.

ContextMenu.PlacementTarget 是 Label,其中托管菜单项。从 Lavel 可以访问其父树视图。

回答by Emil Nachev

<ContextMenu>
    <MenuItem Header="Edit Item"
                   Command="{Binding EditItemCommand, Mode=OneWay}"
                   CommandParameter="{Binding Path=UIElement.(views:DataGridView.SelectedItems), RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
<ContextMenu>