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

C# WPF:如何设置MenuItem中子菜单项的背景颜色

WPF ContextMenu子菜单项背景样式设置问题

我想把MenuItem的子菜单项背景设置成目标效果(目标效果)。已经给ContextMenu加了样式,但子菜单项的颜色没变化。

修改MenuItem的背景属性后,边框区域的背景没改变,效果如图(修改背景后的效果)。尝试修改边框样式后,效果变成这样(修改边框样式后的效果)。

现有代码

ContextMenu样式

<Style TargetType="{x:Type ContextMenu}" x:Key="conte">
    <Setter Property="Background" Value="{DynamicResource PrimaryDark}" />
    <Setter Property="Foreground" Value="{DynamicResource Secendery}" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="HasDropShadow" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding Foreground}" BorderThickness="0.5" CornerRadius="5">
                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle">
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

尝试的MenuItem ItemContainerStyle

<Style TargetType="{x:Type MenuItem}" x:Key="conteItem">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="{DynamicResource Secendery}" />
    <Setter Property="Padding" Value="5,5,5,5" />
    <Setter Property="Foreground" Value="{DynamicResource PrimaryDark}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Border x:Name="Border" BorderBrush="{DynamicResource Secendery}" CornerRadius="5" Background="{DynamicResource PrimaryDark}">
                    <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle">
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

解决方案

问题根源

你的conteItem样式有两个核心问题:

  1. ControlTemplate未指定TargetType="{x:Type MenuItem}",导致所有模板绑定失效
  2. 模板仅用StackPanel作为ItemsHost,完全丢失了MenuItem的核心结构(Header显示、子菜单触发逻辑、交互状态反馈等),同时没有关联子菜单弹出的ContextMenu样式

修正后的完整样式

1. 子菜单专用ContextMenu样式

先定义子菜单的ContextMenu样式,确保弹出的子菜单背景和边框符合目标效果:

<Style TargetType="{x:Type ContextMenu}" x:Key="SubContextMenu">
    <Setter Property="Background" Value="{DynamicResource PrimaryDark}" />
    <Setter Property="Foreground" Value="{DynamicResource Secendery}" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="HasDropShadow" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border x:Name="Border" 
                        Background="{TemplateBinding Background}" 
                        BorderBrush="{TemplateBinding Foreground}" 
                        BorderThickness="0.5" 
                        CornerRadius="5">
                    <StackPanel IsItemsHost="True" 
                                KeyboardNavigation.DirectionalNavigation="Cycle"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

2. 完整的MenuItem样式(含子菜单关联)

这个样式会处理主菜单项和子菜单项的显示、交互,同时关联子菜单样式:

<Style TargetType="{x:Type MenuItem}" x:Key="conteItem">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="{DynamicResource Secendery}" />
    <Setter Property="Padding" Value="5,5,5,5" />
    <Setter Property="Foreground" Value="{DynamicResource Secendery}" />
    <!-- 给子菜单指定专用样式 -->
    <Setter Property="ContextMenuStyle" Value="{StaticResource SubContextMenu}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Border x:Name="Border" 
                        BorderBrush="{TemplateBinding BorderBrush}" 
                        BorderThickness="{TemplateBinding BorderThickness}"
                        CornerRadius="5" 
                        Background="{TemplateBinding Background}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <!-- 显示MenuItem的标题 -->
                        <ContentPresenter Grid.Column="1" 
                                          Content="{TemplateBinding Header}"
                                          Margin="{TemplateBinding Padding}"
                                          VerticalAlignment="Center"/>
                        <!-- 子菜单展开箭头 -->
                        <Path x:Name="Arrow" 
                              Grid.Column="2"
                              Data="M0,0 L0,2 L4,1 z" 
                              Fill="{TemplateBinding Foreground}"
                              Margin="4,0,4,0"
                              Visibility="Collapsed"
                              VerticalAlignment="Center"/>
                    </Grid>
                </Border>
                <!-- 交互状态触发器 -->
                <ControlTemplate.Triggers>
                    <!-- 鼠标悬停时的背景 -->
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Border" Property="Background" Value="{DynamicResource PrimaryDark}" />
                    </Trigger>
                    <!-- 有子菜单时显示箭头 -->
                    <Trigger Property="HasItems" Value="True">
                        <Setter TargetName="Arrow" Property="Visibility" Value="Visible" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <!-- 让子菜单项自动继承当前样式 -->
    <Style.Resources>
        <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource conteItem}"/>
    </Style.Resources>
</Style>

3. 主ContextMenu样式调整

确保主ContextMenu使用修正后的MenuItem样式:

<Style TargetType="{x:Type ContextMenu}" x:Key="conte">
    <Setter Property="Background" Value="{DynamicResource PrimaryDark}" />
    <Setter Property="Foreground" Value="{DynamicResource Secendery}" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="HasDropShadow" Value="True" />
    <!-- 关联MenuItem容器样式 -->
    <Setter Property="ItemContainerStyle" Value="{StaticResource conteItem}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border x:Name="Border" 
                        Background="{TemplateBinding Background}" 
                        BorderBrush="{TemplateBinding Foreground}" 
                        BorderThickness="0.5" 
                        CornerRadius="5">
                    <StackPanel IsItemsHost="True" 
                                KeyboardNavigation.DirectionalNavigation="Cycle"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

关键说明

  • 通过ContextMenuStyle属性为MenuItem的子菜单指定专用样式,确保子菜单的背景边框和主菜单一致
  • MenuItem模板必须包含Header显示区域和子菜单箭头,同时通过触发器处理鼠标悬停等交互状态
  • 利用Style.Resources让嵌套的子菜单项自动继承当前样式,无需重复设置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:24:59