You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF:修改MenuItem的IsSubmenuOpen颜色且保留下拉弹窗功能

问题描述

我正在学习复刻Windows平台上IntelliJ的标题栏菜单,WPF MenuItem默认的颜色行为如下:

  • 处于IsMouseOver且未触发IsSubmenuOpen时,背景为低透明度蓝色
  • 触发IsSubmenuOpen时,背景为低透明度蓝色

我想要改成IntelliJ的样式:

  • 处于IsMouseOver且未触发IsSubmenuOpen时,无颜色变化
  • 触发IsSubmenuOpen时,背景为深蓝色
  • 触发IsSubmenuOpen时,前景为白色

我找到了一段能实现颜色效果的代码,但它会禁用MenuItem打开下拉子菜单的功能,代码如下:

<Style x:Key="TitleBarMenuItem"  TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Border Background="{TemplateBinding Background}">
                    <ContentPresenter Content="{TemplateBinding Header}" Margin="35 5 10 5" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSubmenuOpen" Value="True">
                        <Setter Property="Foreground"  Value="White"/>
                        <Setter Property="Background"  Value="#2675BF"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

请问如何在实现上述颜色变化的同时,保留MenuItem的下拉功能?


解决方案

问题出在你自定义的ControlTemplate里——默认的MenuItem模板包含了触发子菜单展开的Popup控件和交互逻辑,完全重写模板后删掉这些关键部分,就会导致子菜单无法打开。

以下两种方式可以实现需求,同时保留下拉功能:

方式一:仅修改触发器(推荐)

无需重写整个模板,直接基于默认样式添加触发器覆盖颜色行为即可,这种方式能完整保留默认交互逻辑:

<Style x:Key="TitleBarMenuItem" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
    <Style.Triggers>
        <!-- 取消MouseOver状态下的背景变化 -->
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
        </Trigger>
        <!-- 设置IsSubmenuOpen状态下的样式 -->
        <Trigger Property="IsSubmenuOpen" Value="True">
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Background" Value="#2675BF"/>
        </Trigger>
    </Style.Triggers>
</Style>

方式二:重写模板但保留子菜单控件

如果一定要重写模板,必须保留名为PART_Popup的控件(WPF MenuItem依赖该命名控件处理子菜单展开逻辑),完整示例如下:

<Style x:Key="TitleBarMenuItem" TargetType="{x:Type MenuItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Grid>
                    <!-- 主内容显示区域 -->
                    <Border x:Name="Border" Background="{TemplateBinding Background}" Padding="35 5 10 5">
                        <ContentPresenter Content="{TemplateBinding Header}" />
                    </Border>
                    <!-- 子菜单Popup(必须保留PART_Popup命名) -->
                    <Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom"
                           IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
                           Focusable="False">
                        <Border x:Name="SubmenuBorder" Background="#FFFFFF" BorderThickness="1" BorderBrush="#E0E0E0">
                            <ScrollViewer x:Name="SubmenuScrollViewer" CanContentScroll="True">
                                <ItemsPresenter x:Name="ItemsPresenter" />
                            </ScrollViewer>
                        </Border>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <!-- 取消MouseOver状态下的背景变化 -->
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Border" Property="Background" Value="Transparent"/>
                    </Trigger>
                    <!-- 设置IsSubmenuOpen状态下的样式 -->
                    <Trigger Property="IsSubmenuOpen" Value="True">
                        <Setter TargetName="Border" Property="Background" Value="#2675BF"/>
                        <Setter Property="Foreground" Value="White"/>
                    </Trigger>
                    <!-- 没有子项时隐藏Popup -->
                    <Trigger Property="HasItems" Value="False">
                        <Setter TargetName="PART_Popup" Property="Visibility" Value="Collapsed"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

内容的提问来源于stack exchange,提问作者Jack J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 17:35:30