我正在尝试将命令绑定到WPF中的menuitem。我正在使用与我所有其他命令绑定相同的方法,但我无法弄清楚为什么它在这里不起作用。
我目前正在绑定我的命令:
Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MyCommand}"
这是它出错的地方(这是在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>
...
第一个命令绑定的工作原理应该如此,但第二个命令绑定拒绝执行任何操作。 我已经尝试更改祖先级别并命名我的控件通过ElementName而不是RelativeSource访问它,但仍然没有变化。它一直说“找不到参考资料的来源......”
我错过了什么?
答案 0 :(得分:26)
(编辑)由于你提到这是在ItemsControl的模板中,所以情况有所不同:
1)从这个博客获取BindingProxy类(并阅读博客,因为这是有趣的信息):How to bind to data when the DataContext is not inherited。
ItemsControl(或ContextMenu)中的元素基本上不是可视树或逻辑树的一部分,因此无法找到UserControl的DataContext。我很抱歉没有在这里写更多内容,但作者已经做好了一步一步的解释,所以我无法用几行完整解释。
2)做这样的事情:(你可能需要调整一下以使其在你的控制下工作):
一个。这将使您可以使用StaticResource:
访问UserControl DataContext<UserControl.Resources>
<BindingProxy
x:Key="DataContextProxy"
Data="{Binding}" />
</UserControl.Resources>
湾这使用了(a)中定义的DataContextProxy:
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" CommandParameter="{Binding Name}"
Command="{Binding Path=Data.RemoveCommand, Source={StaticResource DataContextProxy}}"/>
</ContextMenu>
这对我们来说很有用,比如树和数据网格。
答案 1 :(得分: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>
答案 2 :(得分:5)
koshdim就是现场,它就像一个魅力!谢谢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>
答案 3 :(得分:3)
这是一个棘手的问题,你肯定会找到一个快速的解决方法,但这是一个无魔法解决方案:
<Button Height="40" Margin="0,2,0,0" CommandParameter="{Binding Name}"
Tag={Binding}
Command = "{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ConnectCommand}">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove"
CommandParameter="{Binding Path=PlacementTarget.Tag.Name, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"
Command="{Binding Path=PlacementTarget.Tag.RemoveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
</ContextMenu>
</Button.ContextMenu>
...
归结为使用Tag
的{{1}}(此处为PlacementTarget
)。