[英]WPF Databinding ContextMenuItem's CommandParameter to TreeViewItem's DataContext
I am using the Command pattern with (among other things) a context menu on a TreeViewItem, which uses HierarchicalDataTemplates. 我正在将Command模式与TreeViewItem上的上下文菜单结合使用,该菜单使用HierarchicalDataTemplates。 The MainWindowViewModel (a static resource for the Window) has properties that expose singleton objects that in turn have properties that represent the commands.
MainWindowViewModel(Window的静态资源)具有暴露单例对象的属性,这些对象又具有表示命令的属性。 I am able to execute the command just fine, but some of the commands need to pass the TreeViewItem's DataContext as the CommandParameter.
我能够很好地执行命令,但是某些命令需要将TreeViewItem的DataContext作为CommandParameter传递。
Here's a specific example: One node of the tree has the ItemsSource bound to an ObservableCollection of individual AnalysisMain objects. 这是一个特定的示例:树的一个节点将ItemsSource绑定到单个AnalysisMain对象的ObservableCollection。 Each of the resulting subnodes has a ContextMenu (with a DataContext bound to the AnalysisController) which has (among others) a Remove MenuItem.
每个结果子节点都有一个ContextMenu(绑定有DataContext的AnalysisController),该菜单具有(除其他功能之外)Remove MenuItem。 The Remove MenuItem's Command property is bound to the CommandRemove command on the AnalysisController singleton object (and it executes just fine).
Remove MenuItem的Command属性绑定到AnalysisController单例对象上的CommandRemove命令(并且执行得很好)。 But this also requires the CommandParameter to be bound to the AnalysisMain object that serves as the DataContext for the subnodes in the tree.
但这还要求将CommandParameter绑定到AnalysisMain对象,该对象用作树中子节点的DataContext。 I have tried using RelativeSource with the AncestorType set to TreeViewItem and the Path set to DataContext:
我已经尝试过将RelativeSource与AncestorType设置为TreeViewItem并将Path设置为DataContext:
<HierarchicalDataTemplate DataType="{x:Type vmAnalysis:AnalysisMain}">
<WrapPanel Orientation="Horizontal">
<Image Source="Analysis\Icon_Analysis_Main_16_Normal.png" Margin="0,0,2,0" Width="16"/>
<TextBlock Text="{Binding TreeViewTitle}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{StaticResource mainWindowViewModel}">
<MenuItem Header="Remove" Command="{Binding Path=AnalysisController.CommandRemove}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=4}, Path=DataContext}">
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</WrapPanel>
</HierarchicalDataTemplate>
Without the AncestorLevel set, when I open the ContextMenu, I get the following in the Output window: 在没有设置AncestorLevel的情况下,当我打开ContextMenu时,将在“输出”窗口中获得以下内容:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TreeViewItem', AncestorLevel='4''.
System.Windows.Data错误:4:找不到参考'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.TreeViewItem',AncestorLevel ='4''的绑定源。 BindingExpression:Path=DataContext;
BindingExpression:路径= DataContext的; DataItem=null;
的DataItem = NULL; target element is 'MenuItem' (Name='');
目标元素是'MenuItem'(Name =''); target property is 'CommandParameter' (type 'Object')
目标属性是“ CommandParameter”(类型“ Object”)
I have tried several values for the AncestorLevel to no avail. 我已经尝试了AncestorLevel的几个值无济于事。
From examining the Visual Tree in Christian Mosers WPF Inspector, I don't see the context menu in the visual tree. 通过检查Christian Mosers WPF检查器中的可视树,我看不到可视树中的上下文菜单。 Although the TreeViewItem shows the DataContext object.
虽然TreeViewItem显示了DataContext对象。 I just need a way to "navigate" to it in order to bind to it.
我只需要一种“导航”到它的方法以绑定到它。
As an alternative, I have tried leaving the ContextMenu DataContext alone and setting the Command Binding's Source to point back to the AnalysisController. 作为一种替代方法,我尝试不使用ContextMenu DataContext并将命令绑定的Source设置为指向AnalysisController。 This also works for executing the command, but I am not able to bind to the TreeViewItem's DataContext for the CommandParameter:
这也适用于执行命令,但是我无法为CommandParameter绑定到TreeViewItem的DataContext:
<ContextMenu>
<MenuItem Header="Remove" Command="{Binding Source={StaticResource mainWindowViewModel}, Path=AnalysisController.CommandRemove}"
CommandParameter="{Binding Source={RelativeSource Self}, Path=DataContext}">
</MenuItem>
</ContextMenu>
I have also tried just using CommandParameter="{Binding}", which also doesn't work. 我也尝试过仅使用CommandParameter =“ {Binding}”,这也不起作用。 (In both cases, I just get null sent as the parameter. No warning / error is written to the Output window.) EDIT: For anyone else with this problem, the second option was doomed from the beginning, because I mistakenly put in Source={RelativeSource Self}, which would refer to the MenuItem and not the TreeViewItem.
(在两种情况下,我只是将null作为参数发送。没有警告/错误被写入到“输出”窗口。)编辑:对于其他有此问题的人,第二个选项从一开始就注定了失败,因为我错误地将其放在Source中= {RelativeSource Self},它将引用MenuItem而不是TreeViewItem。 However, changing this with AncestorType / AncestorLevel makes no difference.
但是,使用AncestorType / AncestorLevel进行更改不会有任何区别。
You have to use PlacementTarget
property of the ContextMenu
您必须使用
ContextMenu
PlacementTarget
属性
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu
DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
</ContextMenu>
</Setter.Value>
</Setter>
And on your MenuItem
do a RelativeSource
to ContextMenu
then use PlacementTarget.DataContext
as your binding to your CommandParameter
并在
MenuItem
对ContextMenu
做一个RelativeSource
,然后使用PlacementTarget.DataContext
作为对CommandParameter
绑定
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.