WPF ContextMenu itemtemplate, menuitem inside menuitem

◇◆丶佛笑我妖孽 提交于 2019-11-27 18:25:31

问题


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:

  • Why is there a MenuItem inside a MenuItem? This doesn't make sense to me as it's not binded to a menuitem list but to a list of TestItemModels.
  • How can I resolve this?

回答1:


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



来源:https://stackoverflow.com/questions/29130567/wpf-contextmenu-itemtemplate-menuitem-inside-menuitem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!