I need to pass current to the context menu command. Here is my xaml code:
<igDP:XamDataGrid.ContextMenu> <ContextMenu> <MenuItem Header="{x:Static r:Resource.Cancel}" Command="{Binding Path=CancelCommand, Mode=OneWay}" CommandParameter="{Binding Path=PlacementTarget, RelativeSource={RelativeSource self}}" /> </ContextMenu> </igDP:XamDataGrid.ContextMenu>
And here is the C# code in my ViewModel:
private void Cancel(object obj) { } private bool CanCancel(object obj) { }
What should I write in "CommandParameter=" so that I get a reference to current row item or at least it's number? I was trying many different options, but in most cases I get null. In some cases I was able to get a reference to the ViewModel, to the context menu, or to the grid, but this does not do any good since I can get reference to it anyway.
Hello Alskey,
It appears that there is an issue with the binding that you have set up in your code-example for your ContextMenu. The MenuItem element does not have a PlacementTarget property, and so I would expect that you would receive a null parameter in your command’s execute method each time. In order to prevent this, I would recommend setting up the following binding for CommandParamter instead:
CommandParameter = “{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget}”
Doing this will pass the XamDataGrid to your command. From there, you can check its active record by checking the ActiveRecord property of the XamDataGrid. If this is all that you need off of the XamDataGrid, you can also bind the CommandParameter’s Path to Parent.PlacementTarget.ActiveRecord as well.
Please let me know if you have any other questions or concerns on this matter.
The above example is just one of many that I tried. I tried your recommendation as well just now and I received a reference to the entire XamDataGrid, which is not very helpful. I need the reference to the record under the mouse pointer.
I am sorry, I missed the last part of your answer. In my case ActiveRecord and ActiveDataItem are both null because I do not have a selected record - I just right click with the mouse on a row, it does not trigger selection.
Thank you for your update. I did not realize that you wanted to get the Record that the mouse was over in this case. I was under the impression that you wanted the ActiveRecord, which is why I had recommended to bind to PlacementTarget.ActiveRecord.
If you instead are looking to get the record that the mouse is over, I would not recommend setting the ContextMenu on the grid itself, but rather, in a Style for DataRecordPresenter. This element makes up the presenter for the records in the grid, and if you attach the ContextMenu to it, you can use a similar binding for it. Here is a sample Style that you could use for this:
<Style TargetType="{x:Type ig:DataRecordPresenter}"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu> <MenuItem Header="Menu Item 1" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget.Record}"> <MenuItem.Command> <local:MyCommand/> </MenuItem.Command> </MenuItem> </ContextMenu> </Setter.Value> </Setter> </Style>
I am sorry, I feel completely dumb, I am not a xaml developer, I just need to fix this one screen. When I followed your recommendation, my commands are not called at all. And when I moved it to an inner tag, compiler cannot find the "local:" prefix. I guess I need to set it up somehow, but I do not know how to do it. Maybe I need to read a book about xaml programming language, but currently it's not on my priority list. I guess I will be fine if I just require the user to select a record to be able to work with it. This is a nice to have feature, but I cannot spend days on it. I understood there is no simple way. Thank you for your help.
I am attaching the sample project to demonstrate the usage of the Style that I had mentioned above.
Regarding the "local" namespace, you need to set up an xmlns namespace at the top of your page that corresponds to the namespace that your ICommand class is under. For example, if the namespace of your command was MyProject.Commands, you would set up an xmlns namespace like so:
xmlns:local="clr-namespace:MyProject.Commands"
Regarding the reason why your command isn't firing, I see in your original code that you were trying to bind the Command property - likely to something that exists on the DataContext of the XamDataGrid. If this is the case, the same binding will not work in the DataRecordPresenter style because the DataRecordPresenter.DataContext is not the same as the XamDataGrid.DataContext. Using your original example, and assuming that the command exists on the object that is serving as the DataContext for the XamDataGrid, you can use the following binding in the DataRecordPresenter style:
Command="{Binding DataPresenter.DataContext.CancelCommand}"
I hope this helps. Please let me know if you have any other questions or concerns on this matter.
XDGContextMenuCase.zip