【问题标题】:WPF Databinding ContextMenuItem's CommandParameter to TreeViewItem's DataContextWPF 数据绑定 ContextMenuItem 的 CommandParameter 到 TreeViewItem 的 DataContext
【发布时间】:2015-01-18 14:11:47
【问题描述】:

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

这是一个具体的例子: 树的一个节点将 ItemsSource 绑定到各个 AnalysisMain 对象的 ObservableCollection。每个生成的子节点都有一个 ContextMenu(具有绑定到 AnalysisController 的 DataContext),它具有(除其他外)一个 Remove MenuItem。 Remove MenuItem 的 Command 属性绑定到 AnalysisController 单例对象上的 CommandRemove 命令(它执行得很好)。但这也需要将 CommandParameter 绑定到充当树中子节点的 DataContext 的 AnalysisMain 对象。我尝试使用将 AncestorType 设置为 TreeViewItem 并将路径设置为 DataContext 的 RelativeSource:

<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 时,我会在输出窗口中看到以下内容:

System.Windows.Data 错误:4:找不到与引用'RelativeSource FindAncestor,AncestorType='System.Windows.Controls.TreeViewItem',AncestorLevel='4''的绑定源。绑定表达式:路径=数据上下文;数据项=空;目标元素是'MenuItem'(名称='');目标属性是'CommandParameter'(类型'Object')

我尝试了几个 AncestorLevel 的值,但均无济于事。

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


作为替代方案,我尝试单独保留 ContextMenu DataContext 并将命令绑​​定的源设置为指向 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 改变它没有任何区别。

【问题讨论】:

  • 我可能对与CommandParameter绑定相关的确切错误有误,实际上CanExecute中的参数为null(意味着绑定不起作用)但在Execute回调中,参数为通过确定。对于我之前发布的代码,您可以尝试在输出窗口中查看是否有任何错误通知。
  • 我检查了(覆盖CanExecute始终返回true),参数仍然为null。

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


【解决方案1】:

您必须使用ContextMenuPlacementTarget 属性

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

然后在你的MenuItem 上做一个RelativeSourceContextMenu 然后使用PlacementTarget.DataContext 作为你的绑定到你的CommandParameter

【讨论】:

  • 我需要使用 Setter 而不是只设置属性吗? (我只在与触发器一起使用时才熟悉 Setter。)这是我最终得到的结果:(在 ContextMenu)DataContext="{Binding PlacementTarget.DataContext,RelativeSource={RelativeSource Self}}" 和 MenuItem CommandParameter="{绑定RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}},Path=PlacementTarget.DataContext}"
  • @Tim 你可以直接使用Property,我刚刚有一个sn-p 使用Styles
  • 我没有对你投反对票,但这对我不起作用。我发布的内容看起来会起作用吗?我也尝试了一种风格(更接近您的原始答案),但这也不起作用。
  • 不,您希望 ContextMenu 的 DataContext 设置为 TreeViewItem 并执行 RelativeSource AncestorType 然后在 MenuItem 上执行 PlacementTarget.DataContext
  • 抱歉,当 XAML 数据绑定变得复杂时,它不是最好的。哪一部分是错的?我有这个:
猜你喜欢
  • 2011-08-17
  • 1970-01-01
  • 2012-04-02
  • 2013-02-02
  • 2012-11-05
  • 2013-11-16
  • 2019-01-21
  • 2010-12-17
  • 1970-01-01
相关资源
最近更新 更多