Reputation: 440
I would like to have global Context Menu that can be used in all datagrids. I defined ContextMenu and style in App.xaml. Main Window is build with many UserControl.
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu">
<MenuItem Header="Import from Excel" Command={???} />
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="DataGrid">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
My problem is how can I bind a command from ViewModel to ContextMenu ?
If the ContextMenu was created in UI Control, then it is simple, because Binding see the ViewModel but I do not have access to ViewModel?
Upvotes: 0
Views: 894
Reputation: 75
The trick here is to use the PlacementTarget property, that contains the element, the ContextMenu is aligned to, what is the DataGrid in our case.
But this is only half of the solution. Because of the data template, the DataContext is set to a dataitem, and not the view model. So you need another relative source lookup, to find the view model. Trick Number 2 is to use the Tag property to bind the view model from outside to the grid, which is the PlacementTarget used above. And there we are.
You can always set the context menu by traversing through the Relative source. For example you set the datacontext of the context menu like below:
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu" DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Import from Excel" Command="{Binding MyCommand}"/>
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
Now in the view where you declare your datagrid you can place the tag for the context menu to understand its binding:
<DataGrid Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}" />
I hope this works for you. The context menu will automatically bind to your command that you have defined in the view model.
Upvotes: 1