c# - WPF 子菜单项不显示在顶层菜单项下
问题描述
我正在尝试在我的 WPF 项目中创建一个基本的菜单系统。我已经通过App.xaml
. 当我单击顶级菜单项时,它的子菜单项不显示。
我怀疑 ContentPresenter 应该已经被重构了,但是我找不到任何关于正确配置的内容。
我应该重构什么以使这种简单的样式与子菜单项一起使用?
中的附加样式App.xaml
:
<Style TargetType="{x:Type Menu}">
<Setter Property="Foreground" Value="#ffffff"/>
<Setter Property="Background" Value="#da4148"/>
</Style>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="#ffffff"/>
<Setter Property="Background" Value="#da4148"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="Border" Background="{TemplateBinding Background}"
SnapsToDevicePixels="True" Uid="Border_38" Margin="0,10,0,0" Padding="3">
<ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Header}"
Grid.Column="1" ContentSource="Header" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="Border" Value="#ffffff"/>
<Setter Property="TextBlock.Foreground" TargetName="Border" Value="#da4148"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
菜单本身:
<DockPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
<Menu DockPanel.Dock="Top" Margin="0" Grid.ColumnSpan="2">
<MenuItem Command="{Binding OpenHomePageCommand}">
<MenuItem.Header>
<StackPanel>
<Image Width="20" Height="20" Source="pack://application:,,,/Resources/Images/home.png" />
<ContentPresenter Content="Home" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Header="{DynamicResource File}" Height="40">
<MenuItem Header="{DynamicResource SaveFile}" Command="{Binding SaveFileCommand}" CommandParameter="{Binding FileDisplayerViewModel.DisplayedFile}" Height="30"/>
<MenuItem Header="{DynamicResource Exit}" Command="{Binding CloseApplicationCommand}" Height="30"/>
</MenuItem>
<MenuItem Header="{DynamicResource Settings}" Height="40">
<MenuItem Header="{DynamicResource Watermark}" Command="{Binding ShowWatermarkWindowCommand}" Height="30"/>
<MenuItem Header="{DynamicResource Language}" Height="30">
<MenuItem Header="{DynamicResource English}" Command="{Binding SetEnglishLanguageCommand}" Height="30"/>
<MenuItem Header="{DynamicResource Hungarian}" Command="{Binding SetHungarianLanguageCommand}" Height="30"/>
</MenuItem>
<MenuItem Header="{DynamicResource ApplicationProperties}" Command="{Binding ShowApplicationPropertiesWindowCommand}" Height="30"/>
</MenuItem>
<MenuItem Header="{DynamicResource Help}" Height="40">
<MenuItem Header="{DynamicResource Help}" Height="30" Command="{Binding OpenHelpWebsiteCommand}"/>
<MenuItem Header="{DynamicResource About}" Height="30" Command="{Binding AboutCommand}"/>
</MenuItem>
</Menu>
</DockPanel>
当我将鼠标移到 MenuItem 上时,悬停样式有效,但未显示子菜单项:
解决方案
Menu
是一个完全由MenuItem
元素组成的树结构。它有一个根节点(标题项)和子项(子项)。如果子项目也是一个节点(可以有孩子),那么这个节点也必须是一个标题。标头也是一个MenuItem
但不同的模板。它有一个popup
包含显示子项的项目面板。
现在,您正在使用一个隐式Style
,它也覆盖所有标题项并将其转换为可以容纳子项且不能展开(无弹出窗口)的普通子项。因此,您基本上缺少Popup
包含子菜单项的 a 。如果您还想覆盖标题模板,则必须添加类似以下内容:
<!-- TopLevelHeader -->
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelHeaderTemplateKey}"
TargetType="{x:Type MenuItem}">
<Border x:Name="Border">
<Grid>
<ContentPresenter Margin="6,3,6,3"
ContentSource="Header"
RecognizesAccessKey="True" />
<Popup x:Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border x:Name="SubmenuBorder"
SnapsToDevicePixels="True"
BorderThickness="1"
Background="{DynamicResource MenuPopupBrush}">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollViewer CanContentScroll="True"
Style="{StaticResource MenuScrollViewer}">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation"
Value="true">
<Setter TargetName="Popup"
Property="PopupAnimation"
Value="None" />
</Trigger>
<Trigger Property="IsHighlighted"
Value="true">
<Setter TargetName="Border"
Property="BorderBrush"
Value="Transparent" />
<Setter Property="Background"
TargetName="Border">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{StaticResource ControlLightColor}" />
<GradientStop Color="{StaticResource ControlMouseOverColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger SourceName="Popup"
Property="AllowsTransparency"
Value="True">
<Setter TargetName="SubmenuBorder"
Property="CornerRadius"
Value="0,0,4,4" />
<Setter TargetName="SubmenuBorder"
Property="Padding"
Value="0,0,0,3" />
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="{StaticResource DisabledForegroundColor}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
或者,您可以MenuItem
明确您的样式并将其直接应用于子菜单项。
但推荐的方法是使用正在使用的资源模板键Menu
。只需定义一个ControlTemplate and override the template resource key (e.g.:
TopLevelHeaderTemplateKey or
SubmenuHeaderTemplateKey`)
标题项:
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelHeaderTemplateKey}"
TargetType="{x:Type MenuItem}">
</ControlTemplate>
您可以在Microsoft Docs中找到完整的默认模板。它显示了如何覆盖所有四个模板资源键。您可以修改它们以满足您的要求。
每个资源键映射到一个MenuItemRole
(例如TopLevelHeader
)。使用资源键描述布局,使用角色描述行为。
推荐阅读
- tcp - 如何监控两个端点中间的简单双向 TCP 套接字流量(Telnet)?
- r - 通过 rmardown 中的循环创建代码片段
- javascript - 替换ul列表子元素
- ios - ExpoCLI-IOS 无法连接到服务器
- apache-calcite - Calcite SqlParser 在使用 MYSQL_5 一致性的 CREATE TABLE 语句中的“int(11)”数据类型规范上失败
- python - 如何在 python 中使用 time.nist.gov 获取东部标准时间
- haskell - 带数字的列表,其数字只有 2、4、6
- bash - 在bash中打印目录的文件名时出错
- node.js - 使用月光在数组中增加对象时遇到问题
- sql - 确定最接近另一个日期值的日期