Reputation: 1940
I have the following xaml:
<ContextMenu ItemsSource="{Binding TestItems}">
<ContextMenu.ItemTemplate>
<DataTemplate DataType="models:TestItemModel">
<MenuItem IsChecked="{Binding IsSelected}" Header="{Binding Header}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
The TestItemModel class only consists of a IsSelected boolean property and a Header string property.
TestItems is a list of TestItemModels.
The data is binded to the contextmenu but it is reflected in the UI as a MenuItem inside a MenuItem (with the additional margins as such, making the menu very big). I can fix this by changing the MenuItem inside the DataTemplate to a TextBox, but then I cannot bind the IsSelected anymore (which I need for visualization properties).
There are a couple of questions I have regarding this:
Upvotes: 13
Views: 15291
Reputation: 33364
Because MenuItem
is the container type and when it translates your view model into visual item it will wrap your template in MenuItem
. In the same way ListBox
will create ListBoxItem
or ListView
will use ListViewItem
. To bind properties of the wrapper you need to use ItemContainerStyle
<ContextMenu ItemsSource="{Binding TestItems}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="IsChecked" Value="{Binding IsSelected}"/>
<Setter Property="Header" Value="{Binding Header}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
or, if you prefer, you can do it partially with ItemTemplate
and ItemContainerStyle
<ContextMenu ItemsSource="{Binding TestItems}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="IsChecked" Value="{Binding IsSelected}"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
In this scenario whatever is in ItemTemplate
will become MenuItem.Header
but IsChecked
property still needs to be bound in ItemContainerStyle
Upvotes: 36