I have a list view that displays a collection of items, each item has as its underlying data a view model (MVVM).
What I would like to do is display different menu items within the context menu when the user right clicks one of these list view items. The menu items displayed is dependent on the type of the item selected (i.e. the type of the underlying view model).
I would expect the below to work, but it does not (no items are displayed in the context menu).
<ListView.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.SelectedItem, RelativeSource={RelativeSource Self}}">
<ContextMenu.Resources>
<DataTemplate DataType="{x:Type ViewModels:ViewModel1}">
<MenuItem Header="DoStuffForVM1" Command="{Binding DoStuffForVM1Command}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:ViewModel2}">
<MenuItem Header="DoStuffForVM2" Command="{Binding DoStuffForVM2Command}"/>
</DataTemplate>
</ContextMenu.Resources>
<ContentPresenter ContentSource="{Binding}" />
</ContextMenu>
</ListView.ContextMenu>
Any ideas?
Thanks.
this works for me:
<ListView.ContextMenu>
<ContextMenu>
<ContentPresenter Content="{Binding Path=PlacementTarget.SelectedItem,
RelativeSource={RelativeSource AncestorType=ContextMenu}}" >
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type ViewModels:ViewModel1}">
<MenuItem Header="DoStuffForVM1" Command="{Binding DoStuffForVM1Command}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:ViewModel2}">
<MenuItem Header="DoStuffForVM2" Command="{Binding DoStuffForVM2Command}"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</ContextMenu>
</ListView.ContextMenu>
That is because you are setting the ContextMenu of the ListView, so your DataContext is the outer context of the ListView, rather than the ViewModel of an individual list item.
You need to set the ContextMenu of each item instead. For instance, using a style:
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="DoStuffForVM1" Command="{Binding DataContext.DoStuffForVM1Command, RelativeSource={RelativeSource AncestorType={x:Type ListView}}"/>
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}"/>
</Style>
</ListView.ItemContainerStyle>
However, the above does not account for the different types of menu.
If you are defining data templates for your listview for each type, the easiest way would be to define the ContextMenu
explicitly in each DataTemplate
.
If not, you'll have to do it with triggers in the style. You'll probably have to write a converter to be able to trigger on object type.