从xaml传递命令参数

时间:2022-08-19 11:49:08

I try to do something like this:

我尝试做这样的事情:

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

but I got null always (I tried also SelectedIndex and SelectedValue)

但我总是得到null(我也试过SelectedIndex和SelectedValue)

if I pass the following parameter to the execution code, it works:

如果我将以下参数传递给执行代码,它的工作原理如下:

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

2 个解决方案

#1


19  

Try something like this in your CommandParameter,

在CommandParameter中尝试这样的事情,

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

I already tested it and it should work.

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

#2


17  

It doesn't work because the ContextMenu is not part of the visual or logical tree of the DataGrid, so it doesn't inherit the DataContext.

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

As far as I know, there is know easy solution to this problem using only the built-in binding system. However, using a simple "proxy" class as explained here, you can work around this problem:

据我所知,只使用内置的绑定系统就可以轻松解决这个问题。但是,使用此处说明的简单“代理”类,您可以解决此问题:

<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>

However you still have a problem: ElementName=myGrid doesn't work (again, because ContextMenu isn't in the visual or logical tree of the DataGrid, so it's not in the same name scope). A simple solution is to bind the SelectedItem of the DataGrid to a property of the ViewModel, and use that property instead of the command parameter:

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

<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>

#1


19  

Try something like this in your CommandParameter,

在CommandParameter中尝试这样的事情,

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

I already tested it and it should work.

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

#2


17  

It doesn't work because the ContextMenu is not part of the visual or logical tree of the DataGrid, so it doesn't inherit the DataContext.

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

As far as I know, there is know easy solution to this problem using only the built-in binding system. However, using a simple "proxy" class as explained here, you can work around this problem:

据我所知,只使用内置的绑定系统就可以轻松解决这个问题。但是,使用此处说明的简单“代理”类,您可以解决此问题:

<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>

However you still have a problem: ElementName=myGrid doesn't work (again, because ContextMenu isn't in the visual or logical tree of the DataGrid, so it's not in the same name scope). A simple solution is to bind the SelectedItem of the DataGrid to a property of the ViewModel, and use that property instead of the command parameter:

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

<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>