2015-01-02 1 views
1

Я успешно реализую меню WPF, в котором элементы верхнего уровня рисуются как большие кнопки, а элементы нижнего уровня рисуются как стандартные пункты меню (см. Мои предыдущие вопросы here и here).Почему у моего MenuItem есть значок, когда я переопределил DataTemplate?

В моей первоначальной попытке на этом мой шаблон нижнего уровня (SubItemTemplate в приведенном ниже примере) содержал изображение и текстовый блок. Результатом было то, что выглядело как обычный элемент меню с пустой областью значков и изображение рядом с текстом в текстовой части элемента меню. Я не ожидал увидеть область значков на визуальном дисплее, так как я думал, что весь визуальный дисплей будет определяться содержимым моего шаблона. Шаблон верхнего уровня (TopLevelItemTemplate) не имеет видимой пустой области.

Когда я удалил свое изображение с шаблона нижнего уровня и заменил его стилем-сетью для свойства Icon, я получил дисплей, который я хотел.

Я не понимаю, как и почему свойство Icon существует на моем нижнем уровне элемента DataTemplate.

Вот мой код. Свойство HasParent используется для выделения элементов меню, которые не являются верхними (то есть те, которые нарисованы с помощью SubItemTemplate). Раздел, который я не понимаю, - это DataTrigger.

Почему в этом триггере есть свойство Icon?

<UserControl.Resources> 
    <Image x:Key="MenuIconResource16" Height="16" Width="16" Source="{Binding Icon32}" x:Shared="False" /> 

    <HierarchicalDataTemplate x:Key="TopLevelItemTemplate" ItemsSource="{Binding Children}"> 
     <StackPanel VerticalAlignment="Bottom" Orientation="Vertical"> 
      <Image Width="32" Height="32" VerticalAlignment="Center" Source="{Binding Icon32}" ToolTip="{Binding UserHint}" /> 
      <TextBlock Text="{Binding Name}"/> 
     </StackPanel> 
    </HierarchicalDataTemplate> 
    <HierarchicalDataTemplate x:Key="SubItemTemplate" ItemsSource="{Binding Children}"> 
     <TextBlock Text="{Binding Name}"/> 
    </HierarchicalDataTemplate> 
</UserControl.Resources> 

<WrapPanel Height="Auto"> 
    <Menu ItemsSource="{Binding DataContext.EventMenu.TopLevel, ElementName=UserControl}" ItemTemplateSelector="{StaticResource MenuItemTemplateSelector}"> 
     <Menu.ItemContainerStyle> 
      <Style TargetType="{x:Type MenuItem}"> 
       <Setter Property="Command" Value="{Binding Command}" /> 
       <Setter Property="CommandParameter" Value="{Binding EventType}"/> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding HasParent}" Value="true"> 
         <Setter Property="Icon" Value="{StaticResource MenuIconResource16}"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Menu.ItemContainerStyle> 
    </Menu> 
</WrapPanel> 
+0

Все, что вы положили в 'DataTemplate', будет использоваться в' MenuItem.Content', когда создается оболочка 'MenuItem'. Поэтому, когда вы помещаете в «DataTemplate», вы становитесь «Content», и когда вы устанавливаете его в «Style», вы устанавливаете свойство «Icon» для оболочки «MenuItem», а «DataTemplate» предоставляет контент. Если вы хотите изменить способ отображения «MenuItem», вам придется изменить «MenuItem.Template», который по умолчанию отличается для верхнего уровня и подменю. – dkozl

ответ

1

Я думал, что весь визуальный дисплей будет определяться содержимым моего шаблона.

@dkozl отметил разницу между DataTemplate и Template - то есть важное различие. Шаблон данных представляет собой фрагмент XAML, который элемент управления владением использует как часть общего элемента управления, который может включать или не включать другие (настраиваемые или жестко закодированные) визуальные элементы и/или другие шаблоны данных. Шаблон управления - это где эта визуальная структура элемента управления определена. Если вы установите/переопределите шаблон управления, то ваше ожидание отсутствия какого-либо другого визуального контента останется верным.

Шаблон верхнего уровня (TopLevelItemTemplate) не имеет видимой пустой области.

Другая вещь, чтобы отметить здесь, что стиль по умолчанию для Menu определяет несколько шаблонов управления для его MenuItems. Эти шаблоны применяются в зависимости от роли «TopLevelHeader», «TopLevelItem», «SubmenuHeader» и «SubmenuItem». Таким образом, вы увидите различное поведение для этих разных пунктов меню. Взгляните на default styles/templates, который должен быть освещен (хотя они довольно сложны).

Почему в этом триггере есть свойство Icon?

Триггер стиля может изменять любое свойство зависимостей элемента управления, к которому он применяется. Поскольку соответствующий триггер стиля применяется к элементу управления MenuItem, он может изменить Icon dependency property, который принадлежит этому элементу управления.

+0

Спасибо! Кажется, что сложность связана с сложностями WPF. Вопрос: Мне пришлось ввести свойство (HasParent), которое используется только для запуска стиля (и в DataTemplateSelector, который выбирает между двумя шаблонами). Есть ли способ получить доступ к описанной вами роли ('TopLevelItem' и т. Д.), Чтобы я мог удалить ненужное свойство из моей модели? –

+0

@LarryLustig не уверен, что я понял, но вы должны иметь доступ к свойству 'Role' из ControlTemplate, используя' Binding RelativeSource = TemplatedParent, Path = Role' и из DataTemplate внутри элемента управления, используя 'Binding RelativeSource = {RelativeSource AncestorType = MenuItem}, Path = Role'. – McGarnagle

 Смежные вопросы

  • Нет связанных вопросов^_^