WPF Подменю стайлинга - PullRequest
       19

WPF Подменю стайлинга

8 голосов
/ 03 августа 2010

У меня есть стиль ContextMenu и стиль MenuItem, оба из которых работают правильно в верхнем меню.Проблема в том, что если я добавлю подменю в пункт меню, то подменю не будет правильно оформлено.Похоже, что на этом этапе вы можете только стилизовать элемент меню, а не собственно подменю, поэтому вы не можете заменить стиль IsMouseOver (он по умолчанию используется для любой темы, которая включена в Windows).

Я искал и искал, самое близкое, что я могу найти, это сообщение на форуме на MSDN http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/69269d23-f97c-42e3-a9dd-0e7c0ba49bdd?prof=required, но на самом деле он также не отвечает правильно на вопрос, так как в его примере та же проблемаЯ бегу в.Любая помощь будет оценена!Заранее спасибо.

Редактировать: Джей, это то, что я делаю.Вот некоторый код в UserControl.Resources как верх моего объекта.

    <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>

, а затем что-то вроде этого для меню

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

Все в слое NewCommand стилизовано правильно,Заходя в NewCommand для просмотра DeleteCommand, сам MenuItem разрабатывается правильно, но фактическое меню по умолчанию соответствует стилю темы Windows, и я пока не вижу способа перезаписать это.Самая важная часть - получить IsMouseOver из подменю, чтобы сохранить тот же внешний вид и структуру главного меню.

Ответы [ 3 ]

14 голосов
/ 03 августа 2010

Как и было обещано, вот код. Спасибо за вашу помощь, Джей, ведите меня в правильном направлении, чтобы наконец найти ответ по MSDN http://msdn.microsoft.com/en-us/library/ms752296.aspx. MenuItem и ContextMenu управляют стилем базового меню, а два других - для пунктов подменю. Путь Джея, возможно, сработал, но я, к сожалению, не смог. Это работает отлично, хотя, и, вероятно, позволяет гораздо больше контроля над стилем подменю.

    <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>
1 голос
/ 03 августа 2010

Как вы применяете свои стили?

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

Вы делаете это и видите неожиданное поведение, или вы пытаетесь определить / применить стили на каждом уровне?

edit 1

Взгляд наВаш XAML, я думаю, проблема в том, что вы стилизуете ContextMenu, но меню ниже имеют тип Menu.Первое, что я бы попробовал, это просто изменить атрибут TargetType для Style на Menu.Посмотрите, будет ли это применяться на всех уровнях.Если нет, я бы изменил его обратно и добавил еще один Style таргетинг Menu и посмотрел бы, если что применяется к подменю.

edit 2

Ладно, думаю, я получил твой ответ.Подменю на самом деле представляет собой MenuItem, что очевидно при взгляде на XAML вместо результата.Шаблон и стиль, которые вы устанавливаете в ContextMenu, также должны быть установлены в любом MenuItem, который является подменю.Я попробовал это и создал стиль, который нацелен на MenuItem с шаблоном управления и триггером на IsMouseOver, и он, кажется, делает то, что вы пытаетесь.

0 голосов
/ 19 июля 2012

Чтобы не дублировать шаблоны, лучше создать один из них с PART_Popup и стрелкой для подменю, но скрывайте ошибку до тех пор, пока вы не сработаете с ролью SubmenuHeader.

...