【问题标题】:How to set foreground and background colors on a WPF Menu control?如何在 WPF 菜单控件上设置前景色和背景色?
【发布时间】:2020-09-29 00:58:35
【问题描述】:

我已经在 WPF 中工作了很长一段时间,但有一些关于样式的基本知识我只是不明白。

如何设置Menu 控件的前景色和背景色?我从这个开始:

    <Menu IsMainMenu="True" Background="#FF3A3A3A" Foreground="White">
        <MenuItem Header="_File">
            <MenuItem Header="_Exit">
            </MenuItem>
        </MenuItem>
    </Menu>

前景色显然是由MenuItem 继承的,但背景不是。下次尝试:

    <Menu IsMainMenu="True" Background="#FF3A3A3A" Foreground="White">
        <MenuItem Background="#FF3A3A3A" Header="_File">
            <MenuItem Header="_Exit">
            </MenuItem>
        </MenuItem>
    </Menu>

现在激活菜单时突出显示/叠加颜色不正确,我看不到设置它们的明显属性。此外,菜单弹出框有一个宽的白色边框,我也不知道如何更改它的颜色(或大小)。

我错过了什么?

【问题讨论】:

    标签: wpf xaml menu menuitem styling


    【解决方案1】:

    您将想要了解更多关于 WPF 中的模板和样式(实际上是 XAML)。在 XAML 中,控件的外观和控件的操作方式是完全不同的两件事。在您的示例中,您可能具有 Foreground 和 Background 属性,但控件的样式\模板不能利用这些属性来显示控件。

    阅读http://wpftutorial.net/Templates.htmlhttp://wpftutorial.net/TemplatesStyles.html,他们会给你一个很好的快速概览。如需更深入的了解,请阅读以下内容:http://msdn.microsoft.com/en-us/library/ee230084.aspx

    如果您使用 Visual Studio 2012 编辑您的 WPF UI,您可以轻松地创建菜单控件正在使用的样式\模板的副本,然后对其进行编辑。如果您使用的是 Visual Studio 2010,则应下载并安装(它可能免费也可能不免费)Expression Blend 以编辑您的 XAML UI。

    提示:如果您使用的是 Visual Studio 2012,请确保您的 Document Outline 窗口窗格始终可见。这对于编辑 XAML UI 非常方便。我的默认折叠在程序的左侧。默认情况下,此窗格在 Expression Blend 中可见。

    在文档大纲中找到 MenuItem 控件。右键单击它并选择编辑模板->编辑副本...

    这将创建菜单项现有外观的副本供您编辑。当您这样做时,您将处于该模板的编辑模式,要“弹出”该模式,请单击“文档大纲”窗口左上角的小图标。

    编辑模板时,可以看到模板的布局和设计。当菜单项作为下拉部分时,它实际上就像弹出菜单(右键菜单)一样显示。浏览那个模板,我马上就跳出来的是这个名为 SubMenuBackgroundBrush 的颜色资源:

    <SolidColorBrush x:Key="SubMenuBackgroundBrush" Color="#FFF5F5F5"/>
    

    如果您搜索 SubMenuBackgroundBrush,您可以看到它用于名为 PART_Popup 的部件:

    <Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" HorizontalOffset="1" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" VerticalOffset="-1">
        <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent">
            <Border x:Name="SubMenuBorder" BorderBrush="#FF959595" BorderThickness="1" Background="{StaticResource SubMenuBackgroundBrush}">
                <ScrollViewer x:Name="SubMenuScrollViewer" Margin="1,0" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                    <Grid RenderOptions.ClearTypeHint="Enabled">
                        <Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                            <Rectangle x:Name="OpaqueRect" Fill="{StaticResource SubMenuBackgroundBrush}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
                        </Canvas>
                        <Rectangle Fill="#F1F1F1" HorizontalAlignment="Left" Margin="1,2" RadiusY="2" RadiusX="2" Width="28"/>
                        <Rectangle Fill="#E2E3E3" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
                        <Rectangle Fill="White" HorizontalAlignment="Left" Margin="30,2,0,2" Width="1"/>
                        <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="true" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
                    </Grid>
                </ScrollViewer>
            </Border>
        </Themes:SystemDropShadowChrome>
    </Popup>
    

    这是您在右键单击显示菜单或下拉菜单的内容时看到的弹出窗口。将引用从:{StaticResource SubMenuBackgroundBrush} 更改为 {TemplateBinding Foreground}

    当您运行程序时,您会看到弹出窗口的主背景发生了变化,但显示图标的区域没有变化。这些也是弹出控件中的所有&lt;Rectangle Fill=" 项目。也改变那些。最后一个对 Rectangle 的引用看起来像是分割图标和文本的线,您可能无法更改它。

    享受美妙的模板世界。它看起来令人困惑,并且需要大量工作。这是。但是当你掌握了它的窍门时,它是一个非常酷的系统。掌握了窍门后,很难再回到任何其他 UI 系统。

    【讨论】:

    • 现在我记得我为什么要避免使用模板。哇,做一些应该如此简单的事情是多么丑陋,完全无法维护的混乱(上面答案中的代码与为 MenuItem 的编辑模板注入的代码不同,并且只有一小部分)。它恢复了我的默认颜色!
    • 看起来只是这样。真的不是。这就像你第一次打开一个大型编程项目。你对所有的文件夹和文件感到不知所措,你不知道该怎么办。随着您越来越多地使用模板和样式,并且您会,它是 XAML 不可或缺的一部分,它看起来不再像那样了。例如,我以前从未看过 MenuItem,也没有使用任何文档,但我能够非常快速地找到调整项。有帮助的一件事是将该样式存储在您的 application.xaml 中,而不是当前的父控件 xaml。
    • 不要误会我的意思,您的答案正是我想要的。也许我使用了一些非默认设置,但在我的例子中,MenuItem 的模板是 313 行长!在许多地方,色彩遍布各处。即使在 App.xaml 中,也需要理解和维护大量代码。
    • 我知道是的。 :) 实际上,弹出菜单没有根据父菜单主题的事实似乎是控件设计者的疏忽。其他控件比这大得多。当您编辑菜单项时,您正在编辑每种视图样式。这就是为什么它比简单的“显示带有颜色的文本”声明更大的原因。它正在做的另一件事是设置行为属性,并将事件与样式挂钩(淡出淡入等)
    • 根据控件的组合方式,您可能已经能够覆盖样式中的设置属性。例如,我注意到声明了模板的 SubMenuBackgroundBrush 资源。如果他们在任何地方都使用它,你可以做一个样式覆盖而不是模板覆盖,然后用一个新的画笔声明那个资源,很少行。但是他们硬编码了一些颜色,所以你不能。
    【解决方案2】:

    我错过了什么?

    控件或多或少可以自定义,自定义控件有两个级别:

    1. 在放置控件的 XAML 中设置 ForegroundBackground 等属性。
    2. 在您的Style 中为控件设置Template,并创建您自己的ControlTemplate

    第二个涉及更多,但它提供了更大的灵活性,可以使控件看起来像您想要的那样。如果是这种情况,听起来这就是您所需要的。查看default ControlTemplate for Menu and MenuItem。您可以复制/粘贴它们并根据需要进行修改。

    <Window.Resources>
        <Style TargetType="{x:Type Menu}">
            <Setter Property="Template">
                <ControlTemplate TargetType="{x:Type Menu}">
                    <!-- your modified template here -->
                </ControlTemplate>
            </Setter>
        </Style>
        <Style TargetType="{x:Type MenuItem}">
            <Setter Property="Template">
                <ControlTemplate TargetType="{x:Type MenuItem}">
                    <!-- your modified template here -->
                </ControlTemplate>
            </Setter>
        </Style>
    </Window.Resources>
    

    【讨论】:

      猜你喜欢
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 2016-03-03
      • 2012-07-10
      • 1970-01-01
      相关资源
      最近更新 更多