1

How to get the PlacementTarget of selected ContextMenu when using MVVM pattern ?

I can get PlacementTarget like this when using MenuItem click event. But how it do it MVVM ?

   public void changeGaugeColor(object sender, RoutedEventArgs e)
    {
        MenuItem tempMenuItem = (MenuItem)sender;

        MenuItem mi = (MenuItem)sender;
        bd = (BidirectionalDial)cm.PlacementTarget;

    }
Dinusha
  • 696
  • 1
  • 14
  • 27
  • Isn't your placement target also part of the same usercontrol you can directly access it using this.yourControlName, what are you trying to do ? – anivas Jul 08 '11 at 08:11
  • Question have to be edited! what do you want? – stukselbax Jul 08 '11 at 09:35
  • If your ViewModel is looking for a placement target, you're doing it wrong. This is all the purview of the View, not the ViewModel. Let the View do all this work from the codebehind. –  Jul 08 '11 at 13:43

1 Answers1

2

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); 
    }
}
Sheridan
  • 68,826
  • 24
  • 143
  • 183