Recursive menu item with default template and itemTemplate

I have a WPF control template for type MenuItem :

 <Style TargetType="{x:Type MenuItem}"> <Setter Property="Background" Value="Transparent" /> <Setter Property="Cursor" Value="Hand" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type MenuItem}"> <Border Background="{TemplateBinding Background}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <ContentControl Content="{TemplateBinding Header}" Margin="5" Grid.Column="1" /> <Path Grid.Column="2" x:Name="Indicator" Data="M1,1 L1,9 9,5Z" Fill="{StaticResource GlyphBrush}" Margin="4" Visibility="Hidden" VerticalAlignment="Center" /> <Popup Name="PART_Popup" Placement="Right" IsOpen="{TemplateBinding IsSubmenuOpen}" AllowsTransparency="True" Grid.Column="0" Grid.ColumnSpan="2" HorizontalOffset="3" VerticalOffset="-1"> <Border Background="Transparent"> <ContentControl Style="{StaticResource PopupContentStyle}"> <ItemsPresenter/> </ContentControl> </Border> </Popup> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Background" Value="{StaticResource ButtonHoverBackgroundBrush}" /> </Trigger> <Trigger Property="IsChecked" Value="false"> <Setter Property="Background" Value="{StaticResource BackgroundBrush}" /> </Trigger> <Trigger Property="HasItems" Value="True"> <Setter TargetName="Indicator" Property="Visibility" Value="Visible" /> </Trigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="Opacity" Value="{StaticResource DisabledTransparency}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="{StaticResource ButtonHoverBackgroundBrush}" /> </Trigger> </Style.Triggers> </Style> 

If you now add items to the MenuItem , the template works flawlessly. But if I try to add items to the associated ObservableCollection , I run into problems, since my ControlTemplate does not use the ItemTemplate original MenuItem anywhere.

This usage causes problems:

 <MenuItem Header="{userInterface:Translation Language}" ItemsSource="{Binding AvailableLanguages}"> <MenuItem.ItemTemplate> <DataTemplate> <MenuItem Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Header}" Header="{Binding}" /> </DataTemplate> </MenuItem.ItemTemplate> </MenuItem> 

MenuItem does not use the above Template , instead, it again accepts my default template.

I tried changing the ItemsPresenter my global template to ItemsControl , but didn't change anything.

How can i solve the problem?

+7
wpf datatemplate menuitem controltemplate
source share
2 answers

I got this fix by changing ItemTemplate to ItemContainerStyle : this is the result:

  <MenuItem Header="{userInterface:Translation Language}" ItemsSource="{Binding AvailableLanguages}"> <MenuItem.ItemContainerStyle> <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}"> <Setter Property="Header" Value="{Binding Name}" /> <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}" /> <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}" /> <Setter Property="IsChecked" Value="{Binding IsSelected}"> </Setter> </Style> </MenuItem.ItemContainerStyle> </MenuItem> 

The problem with the initial ItemTemplate is that inside the MenuItem , MenuItem used as the template for the item container. which led to MenuItem inside a MenuItem , where Command and CommandProperty , where on the internal MenuItem , while Style was on the external MenuItem . This caused problems with my Command because the external MenuItem already consumes Click .

Now, using ItemContainerStyle , the installers will be applied to the correct MenuItem , while using the BasedOn property, the entire set of MenuItem global style templates is executed.

+1
source share

Console,

  • What is your style :
 <Style x:Key="MenuItemStyle1" TargetType="{x:Type MenuItem}"> 
  1. And every time you intend to use it, use the named resource:
  <MenuItem Header="Hello" ItemsSource="{Binding AvailableLanguages}" Style="{DynamicResource MenuItemStyle1}"> <MenuItem.ItemTemplate> <DataTemplate> <MenuItem Style="{DynamicResource MenuItemStyle1}" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ChangeLanguageCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Header}"> <MenuItem.Header> <TextBlock Text="Hello" /> </MenuItem.Header> </MenuItem> </DataTemplate> </MenuItem.ItemTemplate> 

Hi

0
source share

All Articles