22

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)

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

<MenuItem Command="{Binding RemoveRow}" CommandParameter="1"> 
2
  • Did you verify that SelectedItem is not null? Commented Nov 16, 2011 at 15:44
  • I don't know if that works for you but you can just check the datagrid SelectedItem property. Commented Mar 24, 2016 at 19:04

2 Answers 2

25

Try something like this in your 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.

Sign up to request clarification or add additional context in comments.

Comments

18

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.

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:

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

3 Comments

Nice answer! i did not know this issue. but explainme plaese if its like this why when i clicked the menu item the RemoveRow is actually called even if the ContextMenu is no part of the tree?
what do you mean "yes, that's right"? i didnt understand why Command="{Binding RemoveRow}" working if the ContextMenu dont know about th DataContext? can you explain me this please?
OK, I misunderstood your question, I thought you were asking for confirmation... You can find more details in this article

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.