ElementName Binding from MenuItem in ContextMenu ElementName Binding from MenuItem in ContextMenu wpf wpf

ElementName Binding from MenuItem in ContextMenu


I found a much simpler solution.

In the code behind for the UserControl:

NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));


As said by others, the 'ContextMenu' is not contained in the visual tree and an 'ElementName' binding won't work. Setting the context menu's 'NameScope' as suggested by the accepted answer only works if the context menu is not defined in a 'DataTemplate'. I have solved this by using the {x:Reference} Markup-Extension which is similar to the 'ElementName' binding but resolves the binding differently, bypassing the visual tree. I consider this to be far more readable than using 'PlacementTarget'. Here is an example:

<Image Source="{Binding Image}">           <Image.ContextMenu>        <ContextMenu>            <MenuItem Header="Delete"                       Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"                      CommandParameter="{Binding}" />        </ContextMenu>    </Image.ContextMenu></Image>

According to the MSDN-documentation

x:Reference is a construct defined in XAML 2009. In WPF, you can use XAML 2009 features, but only for XAML that is not WPF markup-compiled. Markup-compiled XAML and the BAML form of XAML do not currently support the XAML 2009 language keywords and features.

whatever that means... Works for me, though.


Here's another xaml-only workaround. (This also assumes you want what's inside the DataContext, e.g., you're MVVMing it)

Option one, where the parent element of the ContextMenu is not in a DataTemplate:

Command="{Binding PlacementTarget.DataContext.MyCommand,          RelativeSource={RelativeSource AncestorType=ContextMenu}}"

This would work for OP's question. This won't work if you are inside of a DataTemplate. In these cases, the DataContext is often one of many in a collection, and the ICommand you wish to bind to is a sibling property of the collection within the same ViewModel (the DataContext of the Window, say).

In these cases, you can take advantage of the Tag to temporarily hold the parent DataContext which contains both the collection AND your ICommand:

class ViewModel{    public ObservableCollection<Derp> Derps { get;set;}    public ICommand DeleteDerp {get; set;}} 

and in the xaml

<!-- ItemsSource binds to Derps in the DataContext --><StackPanel    Tag="{Binding DataContext, ElementName=root}">    <StackPanel.ContextMenu>        <ContextMenu>            <MenuItem                Header="Derp"                                       Command="{Binding PlacementTarget.Tag.DeleteDerp,                 RelativeSource={RelativeSource                                     AncestorType=ContextMenu}}"                CommandParameter="{Binding PlacementTarget.DataContext,                 RelativeSource={RelativeSource AncestorType=ContextMenu}}">            </MenuItem>