【问题标题】:How to properly create a sub-menu for a menu item in WPF如何为 WPF 中的菜单项正确创建子菜单
【发布时间】:2019-04-25 03:10:25
【问题描述】:

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

这就是我目前的 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>

最好的方法是什么?

【问题讨论】:

  • 你想用ControlTemplate改变菜单结构的哪一部分?
  • @BradleyUffner 我正在尝试添加某种方式来构建子菜单项(就像在屏幕截图中一样,如果我将鼠标悬停在“新建”按钮上,它会在右侧打开另一个菜单) .当前的ControlTemplate 适用于第一级菜单项 (imgur.com/S4bclJv) 但如果我尝试在 XAML 中添加另一个级别,我会得到子菜单项显示在下方而不是侧面,如下所示: imgur.com/S4bclJv
  • @Step 您根本不必为此修改模板,MenuItem 默认处理它。只需将 MenuItem 相互嵌套,我一直都这样做。

标签: c# wpf xaml


【解决方案1】:

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

因为当你开始做这类事情时,完全打破控制是非常非常容易的。模板完全取代了构成您控制的所有内容。尤其要非常小心,确保完成后任何 contentpresenter 或命名部分仍在其中。

一步一步:

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

选择它。

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

向下滚动到模板。

点击右边的小方框。

选择转换为新资源。

你会发现你需要为一些模板添加对东西的引用。

无论如何,确保它有效。

您现在开始使用一个工作模板(而不是一个损坏的模板)。

做一个小改动并测试一下。

重复。

一步一步地满足您的要求。

还有。

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

【讨论】:

    【解决方案2】:

    默认的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>
    

    产生这个结果:

    你可以随心所欲,只要继续嵌套项目......

    【讨论】:

    • 你说得对,我发现这一点比我承认要晚很多!问题是,我一直在尝试设置自己的 MenuItems 的样式,但我无法弄清楚如何在使用自定义样式/模板保持这种嵌套行为的同时保持这种嵌套行为。简单地更改 Style 属性似乎不允许我影响外边框、复选标记、箭头等内容。
    猜你喜欢
    • 1970-01-01
    • 2014-07-19
    • 2016-04-15
    • 1970-01-01
    • 2011-09-09
    • 2016-03-14
    • 2013-12-24
    • 2017-12-24
    • 1970-01-01
    相关资源
    最近更新 更多