开发者

WPF Submenu styling

If I add a submenu to a menu item, then the submenu is not being styled properly. One can only style the menuitem at this point, and not the actual sub menu. Hence one can't replace the IsMouseOver styling which then just defaults to whatever theme is enabled on windows.

How can one style the submenu?


    <Style TargetType="{x:Type MenuItem}">
        <Setter Property="Background" Value="#0f3c5a"></Setter>
        <Setter Property="Foreground" Value="White"></Setter>
        <Style.Triggers>
            <Trigger Property="IsHighlighted" Value="True">
                <Setter Property="Background" Value="Black"></Setter>
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter Property="Foreground" Value="LightGray"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style TargetType="{x:Type ContextMenu}">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <开发者_运维百科;ControlTemplate TargetType="{x:Type ContextMenu}">
                    
                    <!--Here is where you change the border thickness to zero on the menu-->
                    <Border BorderThickness="0" x:Name="Border"  >
                     <StackPanel ClipToBounds="True" Orientation="Vertical"
                     IsItemsHost="True"/>
                     </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter TargetName="Border" Property="Background" Value="#5082a4" />
                        </Trigger>
                    </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

and then something like this for the menu

<ContextMenu Closed="ContextMenu_Closed"  >
    <MenuItem  Command="k:Window1.NewCommand" > 
       <MenuItem  Command="k:Window1.DeleteCommand"/> 
    </MenuItem>
    ...

Everything on the NewCommand layer is styled properly, going inside NewCommand to view DeleteCommand the MenuItem itself is styled properly, but the actual menu is defaulting to the Windows theme styling and I see no way over overwriting that so far. The most important part is to get the IsMouseOver of submenu's to maintain the same look and feel as the main menu structure.


As promised, here's the code. Thanks for your help Jay, lead me in the right direction to finally find an answer on MSDN http://msdn.microsoft.com/en-us/library/ms752296.aspx MenuItem and ContextMenu control the styling for the base menu, and the other two are for the submenu items. Jay's way may have worked, but I couldn't get it to unfortunately. This works perfectly though, and probably allows for much more control over the submenus styling.

    <UserControl.Resources>

    <!-- Separator -->
    <Style TargetType="{x:Type Separator}"
           x:Key="SeparatorStyle">
        <Setter Property="Height"
                Value="1" />
        <Setter Property="Background"
                Value="#0f3c5a" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Separator}">
                    <Rectangle Height="{TemplateBinding Height}"
                               Fill="White" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--Outer menu items-->
    <Style TargetType="{x:Type MenuItem}">
        <Setter Property="Background"
                Value="#0f3c5a"></Setter>
        <Setter Property="Foreground"
                Value="White"></Setter>
        <Style.Triggers>
            <Trigger Property="IsHighlighted"
                     Value="True">
                <Setter Property="Background"
                        Value="Black"></Setter>
            </Trigger>
            <Trigger Property="IsEnabled"
                     Value="False">
                <Setter Property="Foreground"
                        Value="LightGray"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

    <!-- Outer menu -->
    <Style TargetType="{x:Type ContextMenu}">
        <Setter Property="OverridesDefaultStyle"
                Value="True" />
        <Setter Property="SnapsToDevicePixels"
                Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContextMenu}">

                    <!--Here is where you change the border thickness to zero on the menu-->
                    <Border BorderThickness="0"
                            x:Name="Border"
                            Background="Transparent">
                        <StackPanel ClipToBounds="True"
                                    Orientation="Vertical"
                                    IsItemsHost="True" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter TargetName="Border"
                                    Property="Background"
                                    Value="#0f3c5a" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!-- SubmenuItem -->

    <ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}"
                     TargetType="{x:Type MenuItem}">
        <Border Name="Border">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"
                                      SharedSizeGroup="Icon" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto"
                                      SharedSizeGroup="Shortcut" />
                    <ColumnDefinition Width="13" />
                </Grid.ColumnDefinitions>
                <ContentPresenter Name="Icon"
                                  Margin="6,0,6,0"
                                  VerticalAlignment="Center"
                                  ContentSource="Icon" />
                <Border Name="Check"
                        Width="13"
                        Height="13"
                        Visibility="Collapsed"
                        Margin="6,0,6,0"
                        Background="#0f3c5a"
                        BorderThickness="1"
                        BorderBrush="#5082a4">
                    <Path Name="CheckMark"
                          Width="7"
                          Height="7"
                          Visibility="Hidden"
                          SnapsToDevicePixels="False"
                          Stroke="#5082a4"
                          StrokeThickness="2"
                          Data="M 0 0 L 7 7 M 0 7 L 7 0" />
                </Border>
                <ContentPresenter Name="HeaderHost"
                                  Grid.Column="1"
                                  ContentSource="Header"
                                  RecognizesAccessKey="True" />
                <TextBlock x:Name="InputGestureText"
                           Grid.Column="2"
                           Text="{TemplateBinding InputGestureText}"
                           Margin="5,2,0,2"
                           DockPanel.Dock="Right" />
            </Grid>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="Icon"
                     Value="{x:Null}">
                <Setter TargetName="Icon"
                        Property="Visibility"
                        Value="Hidden" />
            </Trigger>
            <Trigger Property="IsChecked"
                     Value="true">
                <Setter TargetName="CheckMark"
                        Property="Visibility"
                        Value="Visible" />
            </Trigger>
            <Trigger Property="IsCheckable"
                     Value="true">
                <Setter TargetName="Check"
                        Property="Visibility"
                        Value="Visible" />
                <Setter TargetName="Icon"
                        Property="Visibility"
                        Value="Hidden" />
            </Trigger>
            <Trigger Property="IsHighlighted"
                     Value="true">
                <Setter TargetName="Border"
                        Property="Background"
                        Value="#5082a4" />
            </Trigger>
            <Trigger Property="IsEnabled"
                     Value="false">
                <Setter Property="Foreground"
                        Value="#0f3c5a" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <!-- SubmenuHeader -->

    <ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}"
                     TargetType="{x:Type MenuItem}">
        <Border Name="Border">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"
                                      SharedSizeGroup="Icon" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto"
                                      SharedSizeGroup="Shortcut" />
                    <ColumnDefinition Width="13" />
                </Grid.ColumnDefinitions>
                <ContentPresenter Name="Icon"
                                  Margin="6,0,6,0"
                                  VerticalAlignment="Center"
                                  ContentSource="Icon" />
                <ContentPresenter Name="HeaderHost"
                                  Grid.Column="1"
                                  ContentSource="Header"
                                  RecognizesAccessKey="True" />
                <TextBlock x:Name="InputGestureText"
                           Grid.Column="2"
                           Text="{TemplateBinding InputGestureText}"
                           Margin="5,2,2,2"
                           DockPanel.Dock="Right" />
                <Path Grid.Column="3"
                      HorizontalAlignment="Center"
                      VerticalAlignment="Center"
                      Data="M 0 0 L 0 7 L 4 3.5 Z"
                      Fill="#0f3c5a" />
                <Popup Name="Popup"
                       Placement="Right"
                       HorizontalOffset="-4"
                       IsOpen="{TemplateBinding IsSubmenuOpen}"
                       AllowsTransparency="True"
                       Focusable="False"
                       PopupAnimation="Fade">
                    <Border Name="SubmenuBorder"
                            SnapsToDevicePixels="True"
                            Background="#0f3c5a"
                            BorderBrush="#0f3c5a"
                            BorderThickness="1">
                        <StackPanel IsItemsHost="True"
                                    KeyboardNavigation.DirectionalNavigation="Cycle" />
                    </Border>
                </Popup>
            </Grid>
        </Border>

        <ControlTemplate.Triggers>
            <Trigger Property="Icon"
                     Value="{x:Null}">
                <Setter TargetName="Icon"
                        Property="Visibility"
                        Value="Collapsed" />
            </Trigger>
            <Trigger Property="IsHighlighted"
                     Value="true">
                <Setter TargetName="Border"
                        Property="Background"
                        Value="#5082a4" />
            </Trigger>
            <Trigger SourceName="Popup"
                     Property="Popup.AllowsTransparency"
                     Value="True">
                <Setter TargetName="SubmenuBorder"
                        Property="CornerRadius"
                        Value="4" />
                <Setter TargetName="SubmenuBorder"
                        Property="Padding"
                        Value="0,3,0,3" />
            </Trigger>
            <Trigger Property="IsEnabled"
                     Value="false">
                <Setter Property="Foreground"
                        Value="#0f3c5a" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>


How are you applying your styles?

Typically, if you define as style in a "high" or "outer" element's Resources, and give it no key, it will apply to all items of the target type below.

Are you doing this and seeing unexpected behaviour, or are you attempting to define/apply styles in-line at each level?

edit 1

Looking at your XAML, I think the issue is that you are styling ContextMenu, but menus below that are of type Menu. The first thing I'd try is to just change the TargetType attribute for the Style to Menu. See if that gets applied at all levels. If not, I'd change it back and add another Style targeting Menu and see if that one gets applied to the submenu.

edit 2

Okay, I think I've got your answer. The submenu is actually a MenuItem, which is obvious when looking at the XAML instead of the result. The template and styling that you're setting on the ContextMenu must also be set on any MenuItem that is a submenu. I tried it out and created a style that targets MenuItem with a control template and trigger for IsMouseOver and it appeared to do what you're trying.


To not duplicate the templates, you're better off creating one with both PART_Popup and arrow for the submenu, but hide the error until you're triggered with Role being SubmenuHeader.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜