【问题标题】:Binding a context menu command parameter to a datagrid property将上下文菜单命令参数绑定到数据网格属性
【发布时间】:2011-06-15 13:11:50
【问题描述】:

在我的 XAML 文件中,我有一个带有上下文菜单的 DataGrid。数据源是一个 ViewModel,它有一个属性 EntityCollection(一个 ObservableCollection)作为 DataGrid 的 ItemsSource,另一个集合 ContextMenu.MenuItems 用作在 DataGrid 上创建上下文菜单的数据源。该集合的元素有一个 Command 属性,我将其绑定到菜单项的 Command 属性:

<DataGrid Name="EntityDataGrid" ItemsSource="{Binding EntityCollection}" Height="450">
  <DataGrid.ContextMenu>
    <ContextMenu ItemsSource="{Binding Path=ContextMenu.MenuItems}">
      <ContextMenu.ItemContainerStyle>
        <Style TargetType="{x:Type MenuItem}">
          <Setter Property="Command" Value="{Binding Command}" />
          <Setter Property="CommandParameter"
                  Value="{Binding ElementName=EntityDataGrid, Path=SelectedItems}" />
        </Style>
      </ContextMenu.ItemContainerStyle>
    </ContextMenu>
  </DataGrid.ContextMenu>
</DataGrid>

菜单项命令的操作在 ViewModel 中具有以下签名:

private void SelectedItemsAction(object parameter)
{
    // Do something with "parameter"
}

现在我的问题是当我点击上下文菜单项时我到达SelectedItemsAction,但parameternull。我相信我的问题出在CommandParameter 属性的设置器中。如您所见,我想将此属性绑定到 DataGrid 的 SelectedItems 属性,方法是将值设置为:

<Setter Property="CommandParameter"
        Value="{Binding ElementName=EntityDataGrid, Path=SelectedItems}" />

我尝试过更简单的值作为测试:

<Setter Property="CommandParameter"
        Value="{Binding ElementName=EntityDataGrid, Path=Height}" />

这里的parameter 仍然是null。然后只是为了测试是否有任何参数到达我的操作方法:

<Setter Property="CommandParameter"
        Value="10" />

这行得通,我的操作方法中的parameter 现在确实是10

CommandParameter 值绑定到EntityDataGrid 的属性我做错了什么?有可能吗?

提前感谢您的帮助!

【问题讨论】:

    标签: .net wpf binding wpfdatagrid


    【解决方案1】:

    您是否尝试过进行祖先绑定?比如:

    <Setter Property="CommandParameter"
            Value="{Binding Path=SelectedItems, 
            RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
    

    【讨论】:

    • 太好了,谢谢,这行得通! (现在我只需要阅读有关 WPF 绑定的更多信息,即可了解您的代码到底在做什么;))
    • 它正在向上查找匹配该类型的项目。第一个使用它作为绑定上下文。
    • 与此同时,我已经阅读了有关绑定的更多内容,现在很清楚为什么我的原始标记不起作用以及为什么您的代码是正确的方式。谢谢解释!
    • 无法更改此设置,因为它只是一个字符编辑,但您需要在 {x:Type DataGrid}} 之后再添加一个右括号
    【解决方案2】:

    ContextMenu 不在可视树的同一部分,因此您不能使用 ElementName 等来引用 DataGrid。您必须改用ContextMenu 中的PlacementTarget。试试这样

    <ContextMenu ItemsSource="{Binding Path=ContextMenu.MenuItems}">
        <ContextMenu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="CommandParameter"
                        Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}},
                                        Path=PlacementTarget.SelectedItems}" />
            </Style>
        </ContextMenu.ItemContainerStyle>
    </ContextMenu>
    

    【讨论】:

    • 谢谢,这也有效! (我将 OffApps Cory 的解决方案标记为已接受的答案,只是因为他提前几个小时回答了。无论如何感谢您的努力!)
    • +1 终于找到了!当我使用 MVVM Light Toolkit 中的 RelayCommandCommandParameter 时,这对我有用。我希望 WPF 能够使 ElementName 工作,无论项目在元素树中的什么位置。感谢分享这个ContextMenu 绑定变体!
    • 我对 MVVM Light 也有同样的经历。尝试了我所知道的所有常见的东西并且成功有限,然后很多其他同事的建议和谷歌发现也失败了。但这个答案正是我所需要的,并且教会了我一些新的东西。所以感谢@Fredrik Hedblad 8 年后。
    猜你喜欢
    • 1970-01-01
    • 2020-08-02
    • 2014-09-12
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多