WPF ContextMenu itemtemplate, пункт меню внутри элемента меню

У меня есть следующий xaml:

<ContextMenu ItemsSource="{Binding TestItems}">
     <ContextMenu.ItemTemplate>
          <DataTemplate DataType="models:TestItemModel">
              <MenuItem IsChecked="{Binding IsSelected}" Header="{Binding Header}"  />
          </DataTemplate>
     </ContextMenu.ItemTemplate>
</ContextMenu>

Класс TestItemModel состоит только из логического свойства IsSelected и свойства Header string.

TestItems представляет собой список TestItemModels.

Данные привязываются к контекстному меню, но они отражаются в пользовательском интерфейсе как MenuItem внутри MenuItem (с дополнительными полями как таковыми, что делает меню очень большим). Я могу исправить это, изменив MenuItem внутри DataTemplate на TextBox, но затем я больше не могу связывать IsSelected (что мне нужно для свойств визуализации).

У меня есть пара вопросов по этому поводу:

  • Почему MenuItem внутри MenuItem? Это не имеет смысла для меня, так как он связан не со списком пунктов меню, а со списком TestItemModels.
  • Как я могу решить это?

1 ответ

Решение

Так как MenuItem это тип контейнера, и когда он переводит вашу модель представления в визуальный элемент, он оборачивает ваш шаблон в MenuItem, Таким же образом ListBox создаст ListBoxItem или же ListView буду использовать 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>

или, если вы предпочитаете, вы можете сделать это частично с ItemTemplate а также 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>

В этом сценарии все, что есть в ItemTemplate станет MenuItem.Header но IsChecked собственность все еще должна быть связана в ItemContainerStyle

Другие вопросы по тегам