MVVM绑定命令到contextmenu项

Val*_*ion 17 wpf mvvm

我正在尝试将命令绑定到WPF中的menuitem.我正在使用与我所有其他命令绑定一样的方法,但我无法弄清楚为什么它在这里不起作用.

我正在绑定我的命令,如下所示:

Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MyCommand}"
Run Code Online (Sandbox Code Playgroud)

这是它出错的地方(这是在UserControl中)

<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}" 
                        Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}">

     <Button.ContextMenu>
         <ContextMenu>
             <MenuItem Header="Remove" CommandParameter="{Binding Name}"
                                      Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.RemoveCommand}"/>
         </ContextMenu>
     </Button.ContextMenu>
     ...
Run Code Online (Sandbox Code Playgroud)

第一个命令绑定就像它应该的那样工作,但第二个命令绑定拒绝做任何事情.我已经尝试更改祖先级别并命名我的控件通过ElementName而不是RelativeSource访问它,但仍然没有变化.它一直说"找不到参考资料的来源......"

我错过了什么?

Met*_*ter 27

(编辑)既然你提到这是在ItemsControl的模板中,事情是不同的:

1)从这个博客获取BindingProxy类(并阅读博客,因为这是有趣的信息):如何在未继承DataContext时绑定到数据.

基本上ItemsControl(或ContextMenu)中的元素不是可视树或逻辑树的一部分,因此无法找到UserControl的DataContext.我很抱歉没有在这里写更多内容,但作者已经做得很好,一步一步地解释它,所以我无法用几句话给出完整的解释.

2)做这样的事情:(你可能需要调整一下以使其在你的控制中工作):

一个.这将使您可以使用StaticResource访问UserControl DataContext:

<UserControl.Resources>
<BindingProxy
  x:Key="DataContextProxy"
  Data="{Binding}" />
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

湾 这使用(a)中定义的DataContextProxy:

<Button.ContextMenu>
 <ContextMenu>
     <MenuItem Header="Remove" CommandParameter="{Binding Name}"
         Command="{Binding Path=Data.RemoveCommand, Source={StaticResource DataContextProxy}}"/>
 </ContextMenu>
Run Code Online (Sandbox Code Playgroud)

这在树和数据网格等方面对我们有用.


kos*_*dim 11

ContextMenu位于不同的逻辑树中,这就是RelativeSource无法工作的原因.但是上下文菜单从其"容器"继承DataContext,在这种情况下它是Button.在通常情况下就足够了,但在您的情况下,您需要两个"数据上下文",ItemsControl项和ItemsControl本身.我认为您别无选择,只能将您的视图模型合并为一个,实现自定义类以用作ItemsControl项数据上下文并包含"Name"和"Remove command",或者您的项目视图模型可以定义RemoveCommand"proxy",即会在内部调用父命令

编辑:我略微改变了狒狒的代码,它必须以这种方式工作:

<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}" 
    Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
    Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}">
            <Button.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Remove" 
                   CommandParameter="{Binding Name}"
                   Command="{Binding Path=PlacementTarget.Tag.DataContext.RemoveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
                </ContextMenu>
            </Button.ContextMenu>
Run Code Online (Sandbox Code Playgroud)


小智 5

koshdim处处可见,它就像一个魅力!!谢谢科什丁

我修改了他的代码以适合我的上下文菜单

    <DataGrid 
        AutoGenerateColumns="False" 
        HeadersVisibility="Column"
        Name="dgLosses"
        SelectedItem="{Binding SelectedItem, Mode= TwoWay}"
        AllowDrop="True"
        ItemsSource="{Binding Losses}"
        Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}">


        <DataGrid.ContextMenu >
            <ContextMenu >
                <MenuItem Header="Move to Top     "   Command="{Binding PlacementTarget.Tag.MoveToTopCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem>
                <MenuItem Header="Move to Period 1"   Command="{Binding PlacementTarget.Tag.MoveToPeriod1Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem>
                <MenuItem Header="Move to Period 2"   Command="{Binding PlacementTarget.Tag.MoveToPeriod2Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem>
                <MenuItem Header="Move to Period 3"   Command="{Binding PlacementTarget.Tag.MoveToPeriod3Command,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" ></MenuItem>                    
            </ContextMenu>
        </DataGrid.ContextMenu>
Run Code Online (Sandbox Code Playgroud)