WPF C# - 更改菜单背景的画笔

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/517279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:27:53  来源:igfitidea点击:

WPF C# - Change the brush of a menu's background

c#wpfmenustylesmenuitem

提问by user62998

Does anyone know how to change the brush for a menu's background? This sounds simple, but I don't see any obvious way to do this. You'd think that the Background property would change it, but it doesn't.

有谁知道如何更改菜单背景的画笔?这听起来很简单,但我没有看到任何明显的方法来做到这一点。您可能认为 Background 属性会改变它,但事实并非如此。

Here's what my menu looks like (notice the default white background):

这是我的菜单的样子(注意默认的白色背景):

Example Code:

示例代码:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">

<Window.Resources>
    <SolidColorBrush x:Key="menuItemBrush"
                     Color="#FF505050" />
</Window.Resources>

<Grid x:Name="mainGrid"
      Background="#FF252525">

    <Menu x:Name="mainMenu"
          Background="{DynamicResource menuItemBrush}"
          Grid.ColumnSpan="2"
          VerticalAlignment="Top">

        <MenuItem x:Name="fileMenu"
                  Background="{DynamicResource menuItemBrush}"
                  Foreground="White"
                  Header="File">

            <MenuItem x:Name="fileOpenMenuItem"
                      Background="{DynamicResource menuItemBrush}"
                      Foreground="White"
                      Header="Open..." />

            <MenuItem x:Name="fileSaveMenuItem"
                      Background="{DynamicResource menuItemBrush}"
                      Foreground="White"
                      Header="Save" />

            <MenuItem x:Name="fileSaveAsMenuItem"
                      Background="{DynamicResource menuItemBrush}"
                      Foreground="White"
                      Header="Save As..." />

            <Separator Style="{DynamicResource menuItemSeperator}" />

            <MenuItem x:Name="fileExitMenuItem"
                      Background="{DynamicResource menuItemBrush}"
                      Foreground="White"
                      Header="Exit" />
        </MenuItem>
    </Menu>
</Grid>

采纳答案by Nate

I'd suggest using a tool called kaxaml for writing styles. It includes several code snippets, a color picker and a nice way to instantly see what changes in the xaml code does. Here is a full menu style for what you are trying to do. Just change the brush colors at the top to suit to your needs.

我建议使用名为 kaxaml 的工具来编写样式。它包括几个代码片段、一个颜色选择器和一种立即查看 xaml 代码中所做更改的好方法。这是您尝试执行的操作的完整菜单样式。只需更改顶部的画笔颜色即可满足您的需求。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>

  <!--**************************
    * STYLE: MenuItem
    ************************** -->
  <SolidColorBrush x:Key="HighlightedBackgroundBrush" Color="#FF797878" />
  <SolidColorBrush x:Key="MenuBackgroundBrush" Color="#FF505050" />
  <SolidColorBrush x:Key="NormalBorderBrush" Color="#FFFFFFFF" />
  <SolidColorBrush x:Key="SolidMenuFontBrush" Color="#FFFFFFFF" />
  <SolidColorBrush x:Key="HighlightedText" Color="#FFFFFFFF" />
  <Style x:Key="{x:Type Menu}" TargetType="{x:Type Menu}">
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Height" Value="25"/>
    <Setter Property="Foreground" Value="{StaticResource SolidMenuFontBrush}"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Menu}">
          <Border
            Background="{StaticResource MenuBackgroundBrush}"
            BorderBrush="{StaticResource MenuBackgroundBrush}"
            BorderThickness="1">
            <StackPanel ClipToBounds="True" Orientation="Horizontal" IsItemsHost="True"/>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
  <Style x:Key="{x:Type MenuItem}" TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type MenuItem}">
          <Border x:Name="Border"
                  Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="1">
            <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 to show an Icon if needed -->
              <ContentPresenter Grid.Column="0" Margin="4,0,6,0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/>

              <!-- Glyph is a checkmark if needed for a checkable menu -->
              <Grid Grid.Column="0" Visibility="Hidden" Margin="4,0,6,0" x:Name="GlyphPanel" VerticalAlignment="Center">
                <Path x:Name="GlyphPanelpath" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,2 L0,4.8 L2.5,7.4 L7.1,2.8 L7.1,0 L2.5,4.6 z" FlowDirection="LeftToRight"/>
              </Grid>

              <!-- Content for the menu text etc -->
              <ContentPresenter Grid.Column="1"
                                Margin="{TemplateBinding Padding}"
                                x:Name="HeaderHost"
                                RecognizesAccessKey="True"
                                ContentSource="Header"/>

              <!-- Content for the menu IGT -->
              <ContentPresenter Grid.Column="2"
                                Margin="8,1,8,1"
                                x:Name="IGTHost"
                                ContentSource="InputGestureText"
                                VerticalAlignment="Center"/>

              <!-- Arrow drawn path which points to the next level of the menu -->
              <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>

              <!-- The Popup is the body of the menu which expands down or across depending on the level of the item -->
              <Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" x:Name="SubMenuPopup" Focusable="false" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
                <Border x:Name="SubMenuBorder" BorderBrush="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}" BorderThickness="1" Padding="2,2,2,2">
                  <Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True">
                    <!-- StackPanel holds children of the menu. This is set by IsItemsHost=True -->
                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
                  </Grid>
                </Border>
              </Popup>
            </Grid>
          </Border>

          <!-- These triggers re-configure the four arrangements of MenuItem to show different levels of menu via Role -->
          <ControlTemplate.Triggers>
            <!-- Role = TopLevelHeader : this is the root menu item in a menu; the Popup expands down -->
            <Trigger Property="Role" Value="TopLevelHeader">
              <Setter Property="Padding" Value="6,1,6,1"/>
              <Setter Property="Placement" Value="Bottom" TargetName="SubMenuPopup"/>
              <Setter Property="MinWidth" Value="0" TargetName="Col0"/>
              <Setter Property="Width" Value="Auto" TargetName="Col3"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="GlyphPanel"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="IGTHost"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/>
            </Trigger>

            <!-- Role = TopLevelItem :  this is a child menu item from the top level without any child items-->
            <Trigger Property="Role" Value="TopLevelItem">
              <Setter Property="Padding" Value="6,1,6,1"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/>
            </Trigger>

            <!-- Role = SubMenuHeader : this is a child menu item which does not have children -->
            <Trigger Property="Role" Value="SubmenuHeader">
              <Setter Property="DockPanel.Dock" Value="Top"/>
              <Setter Property="Padding" Value="0,2,0,2"/>
            </Trigger>

            <!-- Role = SubMenuItem : this is a child menu item which has children-->
            <Trigger Property="Role" Value="SubmenuItem">
              <Setter Property="DockPanel.Dock" Value="Top"/>
              <Setter Property="Padding" Value="0,2,0,2"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="ArrowPanel"/>
            </Trigger>
            <Trigger Property="IsSuspendingPopupAnimation" Value="true">
              <Setter Property="PopupAnimation" Value="None" TargetName="SubMenuPopup"/>
            </Trigger>

            <!-- If no Icon is present the we collapse the Icon Content -->
            <Trigger Property="Icon" Value="{x:Null}">
              <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/>
            </Trigger>

            <!-- The GlyphPanel contains the CheckMark -->
            <Trigger Property="IsChecked" Value="true">
              <Setter Property="Visibility" Value="Visible" TargetName="GlyphPanel"/>
              <Setter Property="Visibility" Value="Collapsed" TargetName="Icon"/>
            </Trigger>

            <!-- Using the system colors for the Menu Highlight and IsEnabled-->
            <Trigger Property="IsHighlighted" Value="true">
              <Setter Property="Background" Value="{StaticResource HighlightedBackgroundBrush}" TargetName="Border"/>
              <Setter Property="Foreground" Value="{StaticResource HighlightedText}"/>
              <Setter Property="BorderBrush" Value="{StaticResource NormalBorderBrush}" TargetName="Border"/>
            </Trigger>
            <Trigger Property="IsHighlighted" Value="false">
              <Setter Property="Background" Value="{StaticResource MenuBackgroundBrush}" TargetName="Border"/>
              <Setter Property="Foreground" Value="{StaticResource SolidMenuFontBrush}"/>
              <Setter Property="BorderBrush" Value="{StaticResource MenuBackgroundBrush}" TargetName="Border"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
              <Setter Property="Foreground" Value="LightGray"/>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
  </Page.Resources>
<Grid x:Name="mainGrid"
      Background="#FF252525">

    <Menu x:Name="mainMenu"
          Grid.ColumnSpan="2"
          VerticalAlignment="Top">

        <MenuItem x:Name="fileMenu"
                  Header="File">

            <MenuItem x:Name="fileOpenMenuItem"
                      Header="Open..." />

            <MenuItem x:Name="fileSaveMenuItem"
                      Header="Save" />

            <MenuItem x:Name="fileSaveAsMenuItem"
                      Background="{DynamicResource menuItemBrush}"
                      Header="Save As..." />
        </MenuItem>
    </Menu>
  </Grid>
</Page>

回答by Micah

You can't do it without overriding the template for the menu item. Deep inside the template is a control called "Part_Popup". You need to change it's background color.

如果不覆盖菜单项的模板,您就无法做到这一点。模板内部是一个名为“Part_Popup”的控件。您需要更改它的背景颜色。