【问题标题】:Pass command parameter from the xaml从 xaml 传递命令参数
【发布时间】:2025-11-28 04:00:02
【问题描述】:

我尝试做这样的事情:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}">
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding RemoveRow}" 
              CommandParameter="{Binding ElementName=myGrid, Path=SelectedItem}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>

但我总是得到空值(我也尝试过 SelectedIndex 和 SelectedValue)

如果我将以下参数传递给执行代码,它会起作用:

<MenuItem Command="{Binding RemoveRow}" CommandParameter="1">

【问题讨论】:

  • 您确认 SelectedItem 不为空吗?
  • 我不知道这是否适合你,但你可以检查 datagrid SelectedItem 属性。

标签: wpf xaml binding mvvm icommand


【解决方案1】:

它不起作用,因为ContextMenu 不是DataGrid 的可视化或逻辑树的一部分,因此它不继承DataContext

据我所知,仅使用内置绑定系统即可轻松解决此问题。但是,使用here 解释的简单“代理”类,您可以解决此问题:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}">
   <DataGrid.Resources>
       <local:BindingProxy x:Key="proxy" Data="{Binding}" />
   </DataGrid.Resources>
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding Data.RemoveRow, Source={StaticResource proxy}}" 
              CommandParameter="{Binding ElementName=myGrid, Path=SelectedItem}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>

但是你仍然有一个问题:ElementName=myGrid 不起作用(同样,因为ContextMenu 不在DataGrid 的可视化或逻辑树中,所以它不在同名范围内)。一个简单的解决方案是将DataGridSelectedItem 绑定到ViewModel 的一个属性,并使用该属性而不是命令参数:

<DataGrid Name="myGrid" ItemSource="{Binding Path=MyCollection}"
          SelectedItem="{Binding SelectedItem}">
   <DataGrid.Resources>
       <local:BindingProxy x:Key="proxy" Data="{Binding}" />
   </DataGrid.Resources>
   <DataGrid.ContextMenu>
       <ContextMenu>
          <MenuItem 
              Command="{Binding Data.RemoveRow, Source={StaticResource proxy}}">
       </ContextMenu>
   </DataGridContextMenu>
</DataGrid>

【讨论】:

  • 不错的答案!我不知道这个问题。但是请解释一下,如果它是这样的,为什么当我单击菜单项时,即使 ContextMenu 不是树的一部分,实际上也会调用 RemoveRow?
  • “是的,没错”是什么意思?如果 ContextMenu 不知道 DataContext,我不明白为什么 Command="{Binding RemoveRow}" 工作?你能给我解释一下吗?
  • 好的,我误解了你的问题,我以为你是在要求确认...你可以在this article找到更多细节
【解决方案2】:

在您的 CommandParameter 中尝试这样的操作,

<DataGrid.ContextMenu>
     <ContextMenu>
           <MenuItem Header="MyHeader" 
                     Command="{Binding MyCommand}"
                     CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=PlacementTarget.SelectedItem}" />
</DataGrid.ContextMenu>

我已经测试过了,它应该可以工作。

【讨论】: