Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursive menu item with default template and itemTemplate

I have a WPF Control template for the MenuItem type:

<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 I do now add items to a MenuItem the template works flawless. But if I try to add items to a bound ObservableCollection I run into problems as my ControlTemplate does not use the ItemTemplate of the 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>

The MenuItem does not use the Template I specified above, instead it does again take my default template.

I tried changing the ItemsPresenter of my global template to a ItemsControl but it did change nothing.

How can I solve the problem?

like image 800
quadroid Avatar asked Nov 06 '15 12:11

quadroid


2 Answers

I got this fixed by changing the ItemTemplate to a 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>

Problem of the initial ItemTemplate is that the MenuItem internal uses a MenuItem as item container template. which resulted in a MenuItem inside a MenuItem where the Command and the CommandProperty where on the inner MenuItem while the Style was on the outer MenuItem. Which was causing Problems with my Command because the outer MenuItem already consumes the Click.

Now using the ItemContainerStyle the setters get applied to the correct MenuItem while using the BasedOn property takes all Setters of the Global MenuItem style.

like image 195
quadroid Avatar answered Oct 07 '22 19:10

quadroid


Console,

  1. Name 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>

Regards

like image 39
Emmanuel DURIN Avatar answered Oct 07 '22 20:10

Emmanuel DURIN