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

如何为WPF MenuItem添加子菜单箭头显示功能?

WPF自定义MenuItem添加子菜单箭头解决方案

我正在学习WPF结合PowerShell使用,已经实现了自定义MenuItem控件,保留了原生MenuItem的全部功能,但目前无法为带有子菜单的菜单项(包括非顶级父项)显示箭头。

当前效果

当前效果

所需效果

所需效果

原实现代码

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Project"
    Width="400" Height="520"
    ResizeMode="CanMinimize"
    WindowStartupLocation="CenterScreen"
    Background="#191919">

<Window.Resources>

    <Style TargetType="MenuItem">
        <Setter Property="Foreground" Value="#E6E6E6"/>
        <Setter Property="Background" Value="#4C4C4C"/>
        <Setter Property="Padding" Value="3"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="MenuItem">
                    <Grid Background="{TemplateBinding Background}">
                        <Border x:Name="Border" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
                            <TextBlock x:Name="MenuItemText" 
                                       Text="{Binding Path=Header, RelativeSource={RelativeSource TemplatedParent}}"
                                       HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="{TemplateBinding Foreground}"/>
                        </Border>

                        <Popup x:Name="SubMenuPopup" IsOpen="{TemplateBinding IsSubmenuOpen}" Placement="Right">
                            <Grid Background="{TemplateBinding Background}">
                                <ItemsPresenter/>
                            </Grid>
                        </Popup>
                    </Grid>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSubmenuOpen" Value="True">
                            <Setter TargetName="MenuItemText" Property="Foreground" Value="#E6E6E6"/>
                            <Setter TargetName="Border" Property="Background" Value="#2B2B2B"/>
                        </Trigger>

                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="MenuItemText" Property="Foreground" Value="#2B2B2B"/>
                            <Setter TargetName="Border" Property="Background" Value="#E6E6E6"/>
                        </Trigger>

                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="MenuItemText" Property="Foreground" Value="#7F7F7F"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>

    <Grid>

        <Menu HorizontalAlignment="Right" VerticalAlignment="Bottom">
            <MenuItem Header="  Apoiar  "/>
            <MenuItem Header="  Sobre  ">
                <MenuItem Header="EmLogs"/>
                <MenuItem Header="Licenças de Terceiros">
                    <MenuItem Header="BrowserDownloadsView"/>
                    <MenuItem Header="BrowsingHistoryView"/>
                    <MenuItem Header="CSVFileView"/>
                    <MenuItem Header="Everything"/>
                    <MenuItem Header="ExecutedProgramsList"/>
                    <MenuItem Header="InstalledDriversList"/>
                    <MenuItem Header="LastActivityView"/>
                    <MenuItem Header="ProcessExplorer" IsEnabled="False"/>
                    <MenuItem Header="RegScanner"/>
                    <MenuItem Header="ShellBagsView"/>
                    <MenuItem Header="System Informer">
                        <MenuItem Header="Licença"/>
                        <MenuItem Header="Licenças de Terceiros"/>
                    </MenuItem>
                    <MenuItem Header="TaskSchedulerView"/>
                    <MenuItem Header="WebBrowserBookmarksView"/>
                    <MenuItem Header="WhatInStartup"/>
                    <MenuItem Header="WinDefLogView"/>
                </MenuItem>
            </MenuItem>
        </Menu>

    </Grid>

</Window>

解决方案

要实现子菜单箭头显示,需在ControlTemplate中添加箭头元素,并通过触发器控制其仅在菜单项有子项(HasItems=True)时显示。具体修改如下:

  1. 将原Border内的TextBlock替换为DockPanel,同时添加箭头元素
  2. 添加触发器,根据HasItems属性控制箭头的可见性
  3. 同步箭头在不同状态下的颜色,保持与整体风格一致

修改后的完整Style代码

<Style TargetType="MenuItem">
    <Setter Property="Foreground" Value="#E6E6E6"/>
    <Setter Property="Background" Value="#4C4C4C"/>
    <Setter Property="Padding" Value="3"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="MenuItem">
                <Grid Background="{TemplateBinding Background}">
                    <Border x:Name="Border" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
                        <!-- 用DockPanel承载文本和箭头 -->
                        <DockPanel HorizontalAlignment="Stretch">
                            <TextBlock x:Name="MenuItemText" 
                                       Text="{Binding Path=Header, RelativeSource={RelativeSource TemplatedParent}}"
                                       HorizontalAlignment="Left" VerticalAlignment="Center" 
                                       Foreground="{TemplateBinding Foreground}"
                                       DockPanel.Dock="Left"/>
                            <!-- 子菜单箭头 -->
                            <TextBlock x:Name="SubmenuArrow"
                                       Text=">"
                                       HorizontalAlignment="Right" VerticalAlignment="Center"
                                       Foreground="{TemplateBinding Foreground}"
                                       Visibility="Collapsed"/>
                        </DockPanel>
                    </Border>

                    <Popup x:Name="SubMenuPopup" IsOpen="{TemplateBinding IsSubmenuOpen}" Placement="Right">
                        <Grid Background="{TemplateBinding Background}">
                            <ItemsPresenter/>
                        </Grid>
                    </Popup>
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsSubmenuOpen" Value="True">
                        <Setter TargetName="MenuItemText" Property="Foreground" Value="#E6E6E6"/>
                        <Setter TargetName="Border" Property="Background" Value="#2B2B2B"/>
                        <Setter TargetName="SubmenuArrow" Property="Foreground" Value="#E6E6E6"/>
                    </Trigger>

                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="MenuItemText" Property="Foreground" Value="#2B2B2B"/>
                        <Setter TargetName="Border" Property="Background" Value="#E6E6E6"/>
                        <Setter TargetName="SubmenuArrow" Property="Foreground" Value="#2B2B2B"/>
                    </Trigger>

                    <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="MenuItemText" Property="Foreground" Value="#7F7F7F"/>
                        <Setter TargetName="SubmenuArrow" Property="Foreground" Value="#7F7F7F"/>
                    </Trigger>

                    <!-- 关键触发器:有子项时显示箭头 -->
                    <Trigger Property="HasItems" Value="True">
                        <Setter TargetName="SubmenuArrow" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

说明:

  • 用DockPanel实现文本左对齐、箭头右对齐的布局,保证菜单排版合理
  • 通过HasItems触发器精准控制箭头显示,只有包含子菜单的菜单项才会展示箭头
  • 同步箭头在鼠标悬停、菜单展开、禁用状态下的颜色,保持与文本风格统一

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:32:05