如何在WPF中为菜单项正确创建子菜单

时间:2019-04-23 22:42:42

标签: c# wpf xaml

我当前正在尝试在WPF / XAML中设置我的MenuItem对象的样式,但是我不知道如何为MenuItem输出子菜单。要明确的是,这是我所追求的:

enter image description here

这是我目前为MenuItem设置样式的方式:

<Style TargetType="{x:Type MenuItem}">
    <Setter Property="Background" Value="{StaticResource GridLightColour}"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="FontSize" Value="15"/>
    <Setter Property="FontFamily" Value="{StaticResource Exo2Light}"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="ScrollViewer.PanningMode" Value="Both"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Grid SnapsToDevicePixels="true">
                    <DockPanel>
                        <Border x:Name="ContentBorder" BorderThickness="1" BorderBrush="{StaticResource GridLightColour}" Background="{StaticResource GridLightColour}">
                            <ContentPresenter x:Name="Content" ContentSource="Header" Margin="7,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </DockPanel>
                    <Popup x:Name="Popup" AllowsTransparency="true" Focusable="false" HorizontalOffset="0" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" VerticalOffset="-1">
                        <Border BorderThickness="0" BorderBrush="{StaticResource ButtonColour}" Background="{StaticResource GridLightColour}">
                            <ScrollViewer x:Name="SubMenuScrollViewer" CanContentScroll="true" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
                                <Grid RenderOptions.ClearTypeHint="Enabled">
                                    <ItemsPresenter x:Name="ItemsPresenter" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="true" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
                                </Grid>
                            </ScrollViewer>
                        </Border>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource MenuButtonMouseOverColour}" TargetName="ContentBorder"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter Property="Foreground" Value="{StaticResource ButtonMouseOverColour}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

执行此操作的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

默认情况下,默认MenuItem已处理这种嵌套。不需要重写控件的模板即可。

<DockPanel>
    <Menu DockPanel.Dock="Top">
        <MenuItem Header="File">
            <MenuItem Header="Open">
                <MenuItem Header="aaaaaaa" />
                <MenuItem Header="bbbbbbbb" />
                <MenuItem Header="ccccc" />
            </MenuItem>
            <MenuItem Header="Close" />
            <MenuItem Header="quit" />
        </MenuItem>
        <MenuItem Header="Edit">
            <MenuItem Header="Cut" />
            <MenuItem Header="Copy" />
            <MenuItem Header="Paste" />
        </MenuItem>
    </Menu>
    <Grid />
</DockPanel>

产生此结果:

enter image description here

您可以将其延伸到最远的位置,只需继续嵌套项目...

enter image description here

答案 1 :(得分:0)

除非您是XAML忍者,否则处理任何模板的最佳方法是从提取默认模板开始。

因为当您开始执行此类操作时完全破坏控件非常容易。模板完全取代了构成控件的所有内容。特别要注意的是,一旦完成,请确保所有contentpresenter或命名部分仍在其中。

逐步:

将所需类型的控件(菜单)添加到视图中。

选择它。

在属性窗口中,找到“杂项”组。

向下滚动到模板。

点击右侧的小框。

选择转换为新资源。

您会发现您需要为某些模板添加对材料的引用。

在任何情况下,请确保其有效。

您现在从一个有效的模板开始(而不是一个损坏的模板)。

进行一些小的更改并进行测试。

重复。

每次只有一个很小的婴儿一步就可以满足您的要求。

也。

与其在代码中定义菜单项,不如从绑定的分层集合中将它们模板化。