WPF Sub-MenuItems不在顶层MenuItems下显示

时间:2019-07-19 16:00:24

标签: c# wpf menu menuitem submenu

我正在尝试在WPF项目中创建一个基本的菜单系统。我已通过App.xaml应用了附加样式。当我单击顶级菜单项时,它的sub-MenuItems不会显示。

我怀疑应该对ContentPresenter进行重构,但是找不到关于正确配置的任何内容。

我应该重构什么才能使这种简单的样式与sub-MenuItems一起使用?

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上时,悬停样式有效,但未显示sub-MenuItem:

not shown sub-menuitems

1 个答案:

答案 0 :(得分:0)

Menu是一个完全由MenuItem元素组成的树结构。它具有根节点(标题项)和子节点(子项)。如果子项也是一个节点(可以有子节点),则该节点也必须是标头。标头也是MenuItem,但模板不同。它有一个popup,其中包含一个显示子项的项目面板。

现在,您正在使用一个隐式Style,它也将覆盖所有标头项目,并将其转换为可以容纳子项目并且不能扩展(没有弹出窗口)的普通子项目。因此,您基本上缺少包含子菜单项的Popup。如果您还想覆盖标题模板,则必须添加类似以下内容:

<!-- 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)。使用资源键描述布局,使用角色描述行为。