如何让WPF Menu控件内的MenuItem平分可用空间且文本居中
解决方案
你遇到的两个问题根源和修改方法如下:
问题原因
- 菜单项自动换行:默认
UniformGrid未指定行数时,会自动将元素排列为近似正方形的行列布局,3个元素时会生成2行2列的网格,导致第三个元素换行。 - 文本无法居中:
MenuItem的默认模板内置了左对齐的样式规则,单独给单个MenuItem设置HorizontalContentAlignment会被默认样式覆盖,无法生效。
完整修改后代码
<Window x:Class="PlaygroundWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PlaygroundWPF" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <!-- Menu全局样式 --> <Style TargetType="{x:Type Menu}"> <Setter Property="OverridesDefaultStyle" Value="True" /> <Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Menu}"> <Border BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Border.BorderBrush> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <GradientStopCollection> <GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" /> <GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" /> </GradientStopCollection> </LinearGradientBrush> </Border.BorderBrush> <Border.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="{DynamicResource ControlLightColor}" Offset="0" /> <GradientStop Color="{DynamicResource ControlMediumColor}" Offset="1" /> </LinearGradientBrush> </Border.Background> <!-- 强制单行排列,所有菜单项平分宽度 --> <UniformGrid Rows="1" ClipToBounds="True" IsItemsHost="True" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- MenuItem全局样式,统一设置对齐规则 --> <Style TargetType="{x:Type MenuItem}"> <Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Padding" Value="0"/> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="20*"/> <RowDefinition Height="20*"/> <RowDefinition Height="60*"/> </Grid.RowDefinitions> <Menu Grid.Row="1"> <MenuItem Background="Green" Header="Top Level Item" /> <MenuItem Background="Yellow" Header="Top Level Header"> <MenuItem Header="Submenu Item" /> <MenuItem Header="Submenu Header"> <MenuItem Header="Submenu Item" /> </MenuItem> </MenuItem> <!-- 新增任意数量菜单项都会自动在同一行平分空间 --> <MenuItem Background="LightBlue" Header="Third Item" /> </Menu> </Grid> </Window>
关键修改点
- 给
UniformGrid添加Rows="1"属性,强制所有顶层菜单项在同一行显示,自动平分水平空间,支持2-5个菜单项的需求。 - 新增
MenuItem全局样式,统一设置拉伸对齐和内容居中,无需给每个MenuItem重复添加属性,子菜单的文本也会自动居中。 - 给
Menu和模板内的Border添加拉伸对齐属性,确保Menu完全占满Grid分配的20%高度空间。
修改后所有顶层菜单项都会在同一行平分全部可用宽度,垂直占满分配的高度,文本自动居中显示,子菜单的功能和样式不受影响。
内容的提问来源于stack exchange,提问作者Sirop4ik
相关产品推荐
相关产品推荐

