简体   繁体   English

WPF数据绑定ContextMenuItem的CommandParameter到TreeViewItem的DataContext

[英]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 并在MenuItemContextMenu做一个RelativeSource ,然后使用PlacementTarget.DataContext作为对CommandParameter绑定

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM