WPF ContextMenu itemtemplate,menuitem里面的menuitem

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29130567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:01:28  来源:igfitidea点击:

WPF ContextMenu itemtemplate, menuitem inside menuitem

c#wpfcontextmenumenuitem

提问by The Cookies Dog

I have the following xaml:

我有以下 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.

TestItemModel 类仅包含一个 IsSelected 布尔属性和一个 Header 字符串属性。

TestItems is a list of TestItemModels.

TestItems 是 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).

数据绑定到上下文菜单,但它在 UI 中反映为 MenuItem 内的 MenuItem(具有额外的边距,使菜单变得非常大)。我可以通过将 DataTemplate 内的 MenuItem 更改为 TextBox 来解决此问题,但随后我无法再绑定 IsSelected(我需要可视化属性)。

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?
  • 为什么 MenuItem 里面有一个 MenuItem?这对我来说没有意义,因为它没有绑定到菜单项列表,而是绑定到 TestItemModels 列表。
  • 我该如何解决这个问题?

回答by dkozl

Because MenuItemis the container type and when it translates your view model into visual item it will wrap your template in MenuItem. In the same way ListBoxwill create ListBoxItemor ListViewwill use ListViewItem. To bind properties of the wrapper you need to use ItemContainerStyle

因为MenuItem是容器类型,当它将您的视图模型转换为可视项时,它会将您的模板包装在MenuItem. 以同样的方式ListBox将创建ListBoxItemListView将使用ListViewItem. 要绑定您需要使用的包装器的属性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 ItemTemplateand ItemContainerStyle

或者,如果您愿意,您可以部分使用ItemTemplateItemContainerStyle

<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 ItemTemplatewill become MenuItem.Headerbut IsCheckedproperty still needs to be bound in ItemContainerStyle

在这种情况下,任何内容都ItemTemplate将成为MenuItem.HeaderIsChecked仍然需要绑定属性ItemContainerStyle