I realise that this is an old post, but someone might find this useful to know. Assuming that you have bound your view to your view model, then you can then bind your ContextMenu.DataContext
to your view model in the following way:
First, name your view UserControl
... I generally name all of mine This
for simplicity. Then remembering that our view model is bound to the DataContext
of the UserControl
, we can bind to the view model using {Binding DataContext, ElementName=This}
.
So now we can bind to the view model, we have to connect that with the ContextMenu.DataContext
. I use the Tag
property of the object with the ContextMenu
(the PlacementTarget
) as that connection, in this example, a Grid
:
<DataTemplate x:Key="YourTemplate" DataType="{x:Type DataTypes:YourDataType}">
<Grid ContextMenu="{StaticResource Menu}" Tag="{Binding DataContext,
ElementName=This}">
...
</Grid>
</DataTemplate>
We can then access the view model properties and commands in the ContextMenu
by binding the ContextMenu.DataContext
property to the PlacementTarget.Tag
property (of the Grid
in our example):
<ContextMenu x:Key="Menu" DataContext="{Binding PlacementTarget.Tag, RelativeSource=
{RelativeSource Self}}">
<MenuItem Header="Delete" Command="{Binding DeleteFile}" CommandParameter=
"{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource
AncestorType=ContextMenu}}" CommandTarget="{Binding PlacementTarget,
RelativeSource={RelativeSource Self}}" />
</ContextMenu>
Note the binding on the MenuItem.CommandTarget
property. Setting this ensures that the target element on which the specified command is raised is the PlacementTarget
, or the Grid
in this case.
Also note the CommandParameter
binding. This binds to the DataContext
of the PlacementTarget
, or the Grid
in this case. The DataContext
of the Grid
will be inherited from the DataTemplate
and so your data item is now bound to the object
parameter in your Command
if you're using some implementation of the ICommand
interface:
public bool CanExecuteDeleteFileCommand(object parameter)
{
return ((YourDataType)parameter).IsInvalid;
}
public void ExecuteDeleteFileCommand(object parameter)
{
Delete((YourDataType)parameter);
}
Or if you are using some kind of RelayCommand
delegates directly in your view model:
public ICommand Remove
{
get
{
return new ActionCommand(execute => Delete((YourDataType)execute),
canExecute => return ((YourDataType)canExecute).IsInvalid);
}
}