Wpf 自定义控件中ContextMenu的正确绑定

Wpf 自定义控件中ContextMenu的正确绑定,wpf,binding,contextmenu,Wpf,Binding,Contextmenu,在自定义控件中找不到ContextMenu菜单项的正确绑定 <ContextMenu x:Key="MyContextMenu"> <MenuItem Header="MyMenuItem" Command="{Binding PlacementTarget.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/> </Cont

在自定义控件中找不到ContextMenu菜单项的正确绑定

<ContextMenu x:Key="MyContextMenu">
    <MenuItem Header="MyMenuItem"
              Command="{Binding PlacementTarget.MyCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>

<Style TargetType="{x:Type local:MyControl}" x:Shared="False">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyControl}">
                <DockPanel ContextMenu="{StaticResource MyContextMenu}">
                    <!--some controls-->
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

MyCommand在MyControl.xaml.cs中定义,是我希望绑定到菜单项的命令


示例中的绑定在DockPanel中查找MyCommand。什么是正确的绑定?

VisualTree中不包含上下文菜单。因此没有数据上下文。。 这样做可以让它工作

<MenuItem Command="{Binding Path=PlacementTarget.DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />

您需要将标签添加到菜单的容器中,并使用placement target绑定到它

查看此示例:

<StackPanel x:Key="ConfigurationListItem" x:Shared="False" Tag="{Binding ElementName=UserControl}">
        <StackPanel.ContextMenu>
            <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" Tag="{Binding}">
                <MenuItem Header="Sync Environment Dependencies" 
                        Command="{Binding Parent.PlacementTarget.Tag.SyncEnvironmentCommand, RelativeSource={RelativeSource Self}}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.DataContext}" />
            </ContextMenu>
        </StackPanel.ContextMenu>
    </StackPanel>

尼姆罗德先生的回答并没有完全解决我的问题,但提供了一种解决方法。以下是有效的方法

ContextMenu的问题在于,您无法使用RelativeSource将元素树遍历到任意控件:您只能到达其容器(您在PlacementTarget中引用的容器)

基本策略是在ContextMenu的容器中分配标记。标记是指您感兴趣的任何控件、命令等。在我的例子中,我将其分配给TemplatedParent,这允许我绑定到MyCommand的MenuItem.命令

<Style TargetType="{x:Type local:MyControl}" x:Shared="False">
    <Style.Resources>
        <ResourceDictionary>
            <ContextMenu x:Key="MyContextMenu">
                <MenuItem Header="MyItem"
                          Command="{Binding Parent.PlacementTarget.Tag.MyCommand, RelativeSource={RelativeSource Self}}"/>
            </ContextMenu>
        </ResourceDictionary>
    </Style.Resources>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:MyControl}">                
                <DockPanel ContextMenu="{StaticResource MyContextMenu}" Tag="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                    <!--some controls-->                
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


我的控件是一个控件。这个建议不起作用,即使在改为控制后。它生成一个绑定erorr,声明MyCommand不是ContextMenu的属性。我的理解是,使用RelativeSource的ContextMenu只能让您返回ContextMenu,然后您可以使用PlacementTarget获取其包含的控件。wpf中的控件是什么?Never usedA控件通常用于创建允许替换其模板的自定义控件。这使得一个控件的外观可以完全换成另一个控件。@DaveK我已经更改了答案,这应该行得通,对不起,昨晚太晚了,没有看到明显的错误