Search code examples
wpfxamlstylescontextmenu

WPF ContextMenu's MenuItems design changes as I get deeper


I have a ContextMenu that I want to override its style.

This is how it looks like: enter image description here

All the SubMenus should look the same as the first one (with the White Highlighted Background)

Here's the XAML:

<ContextMenu>
    <MenuItem Header="blabla">
        <MenuItem Header="Lol"/>
        <MenuItem Header="blabla">
            <MenuItem Header="Lol"/>
            <MenuItem Header="blabla">
                <MenuItem Header="Lol"/>
                <MenuItem Header="blabla">
                    <MenuItem Header="Lol"/>
                </MenuItem>
            </MenuItem>
        </MenuItem>
    </MenuItem>
    <MenuItem Header="Lol"/>
</ContextMenu>

Here's the Style of my ContextMenu:

<SolidColorBrush x:Key="ContextMenuMenuItemBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ContextMenuSubMenuBorderBrush" Color="#CCCEDB"/>
<SolidColorBrush x:Key="ContextMenuSubMenuBackground" Color="#F6F6F6"/>
<Color x:Key="ContextMenuSubMenuDropShadowColor">#808080</Color>
<SolidColorBrush x:Key="ContextMenuTransitionBackground" Color="#E7E8EC"/>
<SolidColorBrush x:Key="ContextMenuMenuItemHighlightedBackground" Color="#EFEFF2"/>
<SolidColorBrush x:Key="ContextMenuSubmenuItemBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ContextMenuSubmenuItemBackgroundHighlighted" Color="#FFFFFF"/>
<SolidColorBrush x:Key="ContextMenuArrowPanelBackgroundHighlighted" Color="#007ACC"/>
<SolidColorBrush x:Key="ContextMenuMenuDisabledForeground" Color="#A2A4A5"/>



<Style TargetType="{x:Type ContextMenu}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Grid Margin="0,0,5,5">
                    <Border x:Name="SubMenuBorder" BorderBrush="#CCCEDB" BorderThickness="1" Background="#F6F6F6" SnapsToDevicePixels="True" Padding="2">
                        <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" />
                        <Border.Effect>
                            <DropShadowEffect Color="#808080" Opacity="0.60" ShadowDepth="3"/>
                        </Border.Effect>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type MenuItem}">
                            <!--Border 1-->
                            <Border x:Name="Border" Background="{StaticResource ContextMenuMenuItemBackground}" BorderThickness="1" SnapsToDevicePixels="True">
                                <Grid x:Name="Grid">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/>
                                        <ColumnDefinition Width="Auto" SharedSizeGroup="MenuTextColumnGroup"/>
                                        <ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/>
                                        <ColumnDefinition x:Name="Col3" Width="14"/>
                                    </Grid.ColumnDefinitions>
                                    <ContentPresenter Grid.Column="0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/>
                                    <ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" x:Name="HeaderHost" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center"/>
                                    <ContentPresenter Grid.Column="2" Margin="8,1,8,1" x:Name="IGTHost" ContentSource="InputGestureText" VerticalAlignment="Center"/>
                                    <Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center">
                                        <Path x:Name="ArrowPanelPath" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/>
                                    </Grid>
                                    <Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" HorizontalOffset="-1" x:Name="SubMenuPopup" Focusable="False" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" AllowsTransparency="True">
                                        <Grid Margin="0,0,5,5">
                                            <!--Border 2-->
                                            <Border x:Name="SubMenuBorder" BorderBrush="{StaticResource ContextMenuSubMenuBorderBrush}" BorderThickness="1" Background="{StaticResource ContextMenuSubMenuBackground}" SnapsToDevicePixels="True">
                                                <Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True" Margin="2">
                                                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                                                </Grid>
                                                <Border.Effect>
                                                    <DropShadowEffect Color="{StaticResource ContextMenuSubMenuDropShadowColor}" Opacity="0.60" ShadowDepth="3"/>
                                                </Border.Effect>
                                            </Border>
                                            <!--Border 3-->
                                            <Border Margin="1,0,0,0" x:Name="TransitionBorder" BorderBrush="{StaticResource ContextMenuTransitionBackground}" BorderThickness="1" Background="{StaticResource ContextMenuTransitionBackground}" SnapsToDevicePixels="True" Width="0" Height="2" HorizontalAlignment="Left" VerticalAlignment="Top" />
                                        </Grid>
                                    </Popup>
                                </Grid>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="Role" Value="TopLevelHeader">
                                    <Setter Property="Padding" Value="6,0,6,2"/>
                                    <Setter TargetName="SubMenuPopup" Property="Placement" Value="Bottom"/>
                                    <Setter TargetName="Col0" Property="MinWidth" Value="0"/>
                                    <Setter TargetName="Col3" Property="Width" Value="Auto"/>
                                    <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                                    <Setter TargetName="IGTHost" Property="Visibility" Value="Collapsed" />
                                    <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                                    <Setter TargetName="SubMenuBorder" Property="BorderThickness" Value="1,1,1,1"/>
                                    <Setter TargetName="SubMenu" Property="Margin" Value="2,3,2,2"/>
                                    <Setter TargetName="TransitionBorder" Property="Width" Value="{Binding ActualWidth, ElementName=Grid}"/>
                                </Trigger>
                                <Trigger Property="Role" Value="TopLevelItem">
                                    <Setter Property="Padding" Value="6,0,6,2"/>
                                    <Setter TargetName="Col0" Property="MinWidth" Value="0"/>
                                    <Setter TargetName="Col3" Property="Width" Value="Auto"/>
                                    <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                                    <Setter TargetName="IGTHost" Property="Visibility" Value="Collapsed"/>
                                    <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                                </Trigger>
                                <Trigger Property="Role" Value="SubmenuHeader">
                                    <Setter Property="DockPanel.Dock" Value="Top"/>
                                    <Setter Property="Padding" Value="10,3,0,3"/>
                                    <Setter TargetName="Border" Property="MinHeight" Value="22"/>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                                </Trigger>
                                <Trigger Property="Role" Value="SubmenuItem">
                                    <Setter Property="DockPanel.Dock" Value="Top"/>
                                    <Setter Property="Padding" Value="10,3,0,3"/>
                                    <Setter TargetName="Border" Property="MinHeight" Value="22"/>
                                    <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsHighlighted" Value="True"/>
                                        <Condition Property="Role" Value="TopLevelHeader"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuMenuItemHighlightedBackground}"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsHighlighted" Value="True"/>
                                        <Condition Property="Role" Value="TopLevelItem"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuMenuItemHighlightedBackground}"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsHighlighted" Value="True"/>
                                        <Condition Property="Role" Value="SubmenuHeader"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackgroundHighlighted}"/>
                                    <Setter TargetName="ArrowPanelPath" Property="Fill" Value="{StaticResource ContextMenuArrowPanelBackgroundHighlighted}"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsHighlighted" Value="True"/>
                                        <Condition Property="Role" Value="SubmenuItem"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackgroundHighlighted}"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsSubmenuOpen" Value="True"/>
                                        <Condition Property="Role" Value="TopLevelHeader"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                                    <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource ContextMenuSubMenuBorderBrush}"/>
                                </MultiTrigger>
                                <Trigger Property="Icon" Value="{x:Null}">
                                    <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Foreground" Value="{StaticResource ContextMenuMenuDisabledForeground}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Whats wrong here?
Why is this happening?


Solution

  • I got it to work but just using your MenuItem Style directly. I got rid of everything else except

        <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type MenuItem}">
                        <!--Border 1-->
                        <Border x:Name="Border" Background="{StaticResource ContextMenuMenuItemBackground}" BorderThickness="1" SnapsToDevicePixels="True">
                            <Grid x:Name="Grid">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/>
                                    <ColumnDefinition Width="Auto" SharedSizeGroup="MenuTextColumnGroup"/>
                                    <ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/>
                                    <ColumnDefinition x:Name="Col3" Width="14"/>
                                </Grid.ColumnDefinitions>
                                <ContentPresenter Grid.Column="0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/>
                                <ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" x:Name="HeaderHost" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center"/>
                                <ContentPresenter Grid.Column="2" Margin="8,1,8,1" x:Name="IGTHost" ContentSource="InputGestureText" VerticalAlignment="Center"/>
                                <Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center">
                                    <Path x:Name="ArrowPanelPath" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/>
                                </Grid>
                                <Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" HorizontalOffset="-1" x:Name="SubMenuPopup" Focusable="False" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" AllowsTransparency="True">
                                    <Grid Margin="0,0,5,5">
                                        <!--Border 2-->
                                        <Border x:Name="SubMenuBorder" BorderBrush="{StaticResource ContextMenuSubMenuBorderBrush}" BorderThickness="1" Background="{StaticResource ContextMenuSubMenuBackground}" SnapsToDevicePixels="True">
                                            <Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True" Margin="2">
                                                <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                                            </Grid>
                                            <Border.Effect>
                                                <DropShadowEffect Color="{StaticResource ContextMenuSubMenuDropShadowColor}" Opacity="0.60" ShadowDepth="3"/>
                                            </Border.Effect>
                                        </Border>
                                        <!--Border 3-->
                                        <Border Margin="1,0,0,0" x:Name="TransitionBorder" BorderBrush="{StaticResource ContextMenuTransitionBackground}" BorderThickness="1" Background="{StaticResource ContextMenuTransitionBackground}" SnapsToDevicePixels="True" Width="0" Height="2" HorizontalAlignment="Left" VerticalAlignment="Top" />
                                    </Grid>
                                </Popup>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Role" Value="TopLevelHeader">
                                <Setter Property="Padding" Value="6,0,6,2"/>
                                <Setter TargetName="SubMenuPopup" Property="Placement" Value="Bottom"/>
                                <Setter TargetName="Col0" Property="MinWidth" Value="0"/>
                                <Setter TargetName="Col3" Property="Width" Value="Auto"/>
                                <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="IGTHost" Property="Visibility" Value="Collapsed" />
                                <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="SubMenuBorder" Property="BorderThickness" Value="1,1,1,1"/>
                                <Setter TargetName="SubMenu" Property="Margin" Value="2,3,2,2"/>
                                <Setter TargetName="TransitionBorder" Property="Width" Value="{Binding ActualWidth, ElementName=Grid}"/>
                            </Trigger>
                            <Trigger Property="Role" Value="TopLevelItem">
                                <Setter Property="Padding" Value="6,0,6,2"/>
                                <Setter TargetName="Col0" Property="MinWidth" Value="0"/>
                                <Setter TargetName="Col3" Property="Width" Value="Auto"/>
                                <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="IGTHost" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                            </Trigger>
                            <Trigger Property="Role" Value="SubmenuHeader">
                                <Setter Property="DockPanel.Dock" Value="Top"/>
                                <Setter Property="Padding" Value="10,3,0,3"/>
                                <Setter TargetName="Border" Property="MinHeight" Value="22"/>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                            </Trigger>
                            <Trigger Property="Role" Value="SubmenuItem">
                                <Setter Property="DockPanel.Dock" Value="Top"/>
                                <Setter Property="Padding" Value="10,3,0,3"/>
                                <Setter TargetName="Border" Property="MinHeight" Value="22"/>
                                <Setter TargetName="ArrowPanel" Property="Visibility" Value="Collapsed"/>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsHighlighted" Value="True"/>
                                    <Condition Property="Role" Value="TopLevelHeader"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuMenuItemHighlightedBackground}"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsHighlighted" Value="True"/>
                                    <Condition Property="Role" Value="TopLevelItem"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuMenuItemHighlightedBackground}"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsHighlighted" Value="True"/>
                                    <Condition Property="Role" Value="SubmenuHeader"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackgroundHighlighted}"/>
                                <Setter TargetName="ArrowPanelPath" Property="Fill" Value="{StaticResource ContextMenuArrowPanelBackgroundHighlighted}"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsHighlighted" Value="True"/>
                                    <Condition Property="Role" Value="SubmenuItem"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackgroundHighlighted}"/>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsSubmenuOpen" Value="True"/>
                                    <Condition Property="Role" Value="TopLevelHeader"/>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Border" Property="Background" Value="{StaticResource ContextMenuSubmenuItemBackground}"/>
                                <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource ContextMenuSubMenuBorderBrush}"/>
                            </MultiTrigger>
                            <Trigger Property="Icon" Value="{x:Null}">
                                <Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="{StaticResource ContextMenuMenuDisabledForeground}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    (I left the Brushes...)

    To apply it only to the context menu in question...

    <ContextMenu>
        <ContextMenu.Resources>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
                ......
            </Style>
        </ContextMenu.Resources>
        <MenuItem Header="blabla">
            <MenuItem Header="Lol"/>
            <MenuItem Header="blabla">
                <MenuItem Header="Lol"/>
                <MenuItem Header="blabla">
                    <MenuItem Header="Lol"/>
                    <MenuItem Header="blabla">
                        <MenuItem Header="Lol"/>
                    </MenuItem>
                </MenuItem>
            </MenuItem>
        </MenuItem>
        <MenuItem Header="Lol"/>
    </ContextMenu>