WPF Context menu doesn't bind to right databound item WPF Context menu doesn't bind to right databound item wpf wpf

WPF Context menu doesn't bind to right databound item


The key thing to remember here is context menus are not part of the visual tree.

Therefore they don't inherit the same source as the control they belong to for binding. The way to deal with this is to bind to the placement target of the ContextMenu itself.

<MenuItem Header="Change" Command="{Binding     Path=PlacementTarget.ChangeCommand,     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>


The cleanest way I have found to bind commands to context menu items involves using a class called CommandReference. You can find it in the MVVM toolkit on Codeplex at WPF Futures.

The XAML might look like this:

<UserControl x:Class="View.MyView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                xmlns:vm="clr-namespace:ViewModel;assembly=MyViewModel"                xmlns:mvvm="clr-namespace:ViewModelHelper;assembly=ViewModelHelper"           <UserControl.Resources>                <mvvm:CommandReference x:Key="MyCustomCommandReference" Command="{Binding MyCustomCommand}" />                <ContextMenu x:Key="ItemContextMenu">                    <MenuItem Header="Plate">                        <MenuItem Header="Inspect Now" Command="{StaticResource MyCustomCommandReference}"                                CommandParameter="{Binding}">                        </MenuItem>                    </MenuItem>               </ContextMenu>    </UserControl.Resources>

MyCustomCommand is a RelayCommand on the ViewModel. In this example, the ViewModel was attached to the view's datacontext in the code-behind.

Note: this XAML was copied from a working project and simplified for illustration. There may be typos or other minor errors.


I had the same issue recently with a ContextMenu located in a ListBox. I tried to bind a command the MVVM way without any code-behind. I finally gave up and I asked a friend for his help. He found a slightly twisted but concise solution. He is passing the ListBox in the DataContext of the ContextMenu and then find the command in the view model by accessing the DataContext of the ListBox. This is the simplest solution that I have seen so far. No custom code, no Tag, just pure XAML and MVVM.

I posted a fully working sample on Github. Here is an excerpt of the XAML.

<Window x:Class="WpfListContextMenu.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        Title="MainWindow" Height="350" Width="268">  <Grid>    <DockPanel>      <ListBox x:Name="listBox" DockPanel.Dock="Top" ItemsSource="{Binding Items}" DisplayMemberPath="Name"               SelectionMode="Extended">        <ListBox.ContextMenu>          <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">            <MenuItem Header="Show Selected" Command="{Binding Path=DataContext.ShowSelectedCommand}"                      CommandParameter="{Binding Path=SelectedItems}" />          </ContextMenu>        </ListBox.ContextMenu>      </ListBox>    </DockPanel>  </Grid></Window>