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

时间:2014-11-20 16:13:30

标签: c# wpf data-binding contextmenu command-pattern

我在TreeViewItem上使用Command模式(以及其他内容)上下文菜单,它使用HierarchicalDataTemplates。 MainWindowViewModel(Window的静态资源)具有公开单个对象的属性,而单个对象又具有表示命令的属性。我能够很好地执行命令,但是有些命令需要将TreeViewItem的DataContext作为CommandParameter传递。

这是一个具体的例子: 树的一个节点将ItemsSource绑定到各个AnalysisMain对象的ObservableCollection。每个生成的子节点都有一个ContextMenu(带有绑定到AnalysisController的DataContext),其中包含一个Remove MenuItem(以及其他)。 Remove MenuItem的Command属性绑定到AnalysisController单例对象上的CommandRemove命令(它执行得很好)。但是这也需要将CommandParameter绑定到AnalysisMain对象,该对象充当树中子节点的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>

如果没有设置AncestorLevel,当我打开ContextMenu时,我会在Output窗口中看到以下内容:

  

System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Controls.TreeViewItem',AncestorLevel ='4''。 BindingExpression:路径= DataContext的;的DataItem = NULL; target元素是'MenuItem'(Name =''); target属性是'CommandParameter'(类型'Object')

我已经为AncestorLevel尝试了几个值无济于事。

通过检查Christian Mosers WPF Inspector中的Visual Tree,我没有在可视化树中看到上下文菜单。虽然TreeViewItem显示DataContext对象。我只需要一种“导航”它的方式来绑定它。


作为替代方案,我尝试单独保留ContextMenu DataContext并将Command Binding的Source设置为指向AnalysisController。这也适用于执行命令,但我无法绑定到CommandParameter的TreeViewItem的DataContext:

<ContextMenu>
    <MenuItem Header="Remove" Command="{Binding Source={StaticResource mainWindowViewModel}, Path=AnalysisController.CommandRemove}"
              CommandParameter="{Binding Source={RelativeSource Self}, Path=DataContext}">
    </MenuItem>
</ContextMenu>

我也尝试过使用CommandParameter =“{Binding}”,这也行不通。 (在这两种情况下,我只是将null作为参数发送。没有警告/错误被写入输出窗口。)编辑:对于有此问题的其他人,第二个选项从一开始就注定失败,因为我错误地输入了Source = {RelativeSource Self},它将引用MenuItem而不是TreeViewItem。但是,使用AncestorType / AncestorLevel更改此选项没有任何区别。

1 个答案:

答案 0 :(得分:1)

您必须使用PlacementTarget

ContextMenu属性
<Setter Property="ContextMenu">
        <Setter.Value>
            <ContextMenu
        DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
            </ContextMenu>
        </Setter.Value>
 </Setter>

MenuItem RelativeSourceContextMenu上,然后使用PlacementTarget.DataContext作为对CommandParameter的约束