C# 如何实施";“超级菜单”;在WPF中?

C# 如何实施";“超级菜单”;在WPF中?,c#,wpf,megamenu,C#,Wpf,Megamenu,我正在尝试使用WPF实现“超级菜单”样式的菜单。要查看web设计中的巨型菜单示例,请参阅 到目前为止,我已经尝试创建一个类似的界面,使用TextBlocks作为菜单的最高级别,然后使用鼠标悬停事件显示位于文本块下方的附加窗口。这既麻烦又不灵活,将来的更改将需要动态添加/删除文本块 我已经考虑过使用WPF菜单控件,因为我知道样式可以被极大地修改,但是我还没有看到任何方法可以使用菜单控件使用的层次模型生成多列布局 有更好的方法吗?我是否必须坚持使用自定义窗口和相对定位?有人能给我举一个已经实现的例子

我正在尝试使用WPF实现“超级菜单”样式的菜单。要查看web设计中的巨型菜单示例,请参阅

到目前为止,我已经尝试创建一个类似的界面,使用TextBlocks作为菜单的最高级别,然后使用鼠标悬停事件显示位于文本块下方的附加窗口。这既麻烦又不灵活,将来的更改将需要动态添加/删除文本块

我已经考虑过使用WPF菜单控件,因为我知道样式可以被极大地修改,但是我还没有看到任何方法可以使用菜单控件使用的层次模型生成多列布局


有更好的方法吗?我是否必须坚持使用自定义窗口和相对定位?有人能给我举一个已经实现的例子吗?

自定义窗口和相对位置基本上就是WPF菜单/MenuItem控件的工作方式。。。但正如你所发现的,这不是小事。最好的办法是重新安装菜单/菜单项控件以满足您的需要。

您可以使用一个菜单项,然后更换
面板以满足您的需要;默认情况下,它使用
StackPanel
,但是
WrapPanel
可能更适合您。默认情况下,弹出和鼠标悬停行为不存在,需要实现


更重要的是利用一种习惯;因为它提供了您需要的弹出行为,而“链接到漫游”提供了鼠标悬停行为。

我想知道是否可以改装Ribbon控件来实现这一点?它提供了选项卡、标签、列等


请谨慎使用此UI设计,并确保它仅在用户明确请求时打开和关闭。当一个弹出式菜单出现在我正在浏览的网站上时,我会非常恼火,我无法让它关闭,除非我想点击它,它就会消失。

你可以使用弹出控件,而不是使用自定义窗口和定位。您可以使用
StaysOpen=false
设置在用户单击屏幕外时将其关闭

如果您可以满足于单击菜单项而不是悬停,则以下自定义控件将起作用:

[TemplatePart(Name="PART_HoverArea", Type=typeof(FrameworkElement))]
[TemplatePart(Name="PART_Popup", Type=typeof(Popup))]
public class MegaMenuItem : HeaderedContentControl
{
    private FrameworkElement hoverArea;
    private Popup popup;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        // Unhook old template
        if (hoverArea != null)
        {
            hoverArea.PreviewMouseUp -= ShowPopupOnMouseDown;
        }

        hoverArea = null;
        popup = null;

        if (Template == null)
            return;

        // Hook up new template
        hoverArea = (FrameworkElement)Template.FindName("PART_HoverArea", this);
        popup = (Popup)Template.FindName("PART_Popup", this);
        if (hoverArea == null || popup == null)
            return;

        hoverArea.PreviewMouseUp += ShowPopupOnMouseDown;
    }

    private void ShowPopupOnMouseDown(object sender, MouseEventArgs e)
    {
        popup.PlacementTarget = hoverArea;
        popup.Placement = PlacementMode.Bottom;
        popup.StaysOpen = false;
        popup.IsOpen = true;
    }
}
您需要一个样式来显示它-类似这样的东西。注意零件模板零件名称:

<Style TargetType="WpfApplication14:MegaMenuItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="WpfApplication14:MegaMenuItem">
                <Grid>
                    <Border Name="PART_HoverArea" Background="#fb9c3b" BorderBrush="White" BorderThickness="0,0,1,0">
                        <ContentPresenter Content="{TemplateBinding Header}" />
                    </Border>

                    <Popup 
                        Name="PART_Popup" 
                        PlacementTarget="{Binding ElementName=HoverArea}"
                        >
                        <Border MinWidth="100" MaxWidth="400" MinHeight="40" MaxHeight="200" Background="#0d81c3">
                            <ContentPresenter Content="{TemplateBinding Content}" />
                        </Border>
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>    
</Style>

然后,菜单的XAML将是:

<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
    <WpfApplication14:MegaMenuItem Header="Parent 1">
        <WrapPanel Margin="5">
            <TextBlock Text="Put any content you want here" Margin="5" />
            <TextBlock Text="Put any content you want here" Margin="5" />
            <TextBlock Text="Put any content you want here" Margin="5" />
        </WrapPanel>
    </WpfApplication14:MegaMenuItem>
    <WpfApplication14:MegaMenuItem Header="Parent 2">
        <WrapPanel Margin="5">
            <TextBlock Text="Put any content you want here" Margin="5" />
            <TextBlock Text="Put any content you want here" Margin="5" />
            <TextBlock Text="Put any content you want here" Margin="5" />
        </WrapPanel>
    </WpfApplication14:MegaMenuItem>
</StackPanel>


使菜单显示在悬停状态要困难得多,因为弹出窗口窃取焦点的方式(您可以显示菜单,但如果将鼠标移到另一个菜单上,则无法轻松隐藏菜单)。为此,自定义窗口可能会更好。

大型菜单是否会在鼠标悬停时下拉?是的。通常,您会在web上看到它们是用JavaScript实现的。当你悬停时,一个多列的面板会下拉下来,上面有不同的副标题。这是一个桌面应用程序,它只包含菜单本身,并且它会停靠在屏幕的顶部,所以鼠标的悬停应该是最小的。如果用户觉得这很烦人,我会把它改为基于点击而不是基于悬停。我会小心微软功能区控件的修改。当开发人员注册使用控件时,它们有非常特定的用途。可能还有其他的“ribbonesque”控件是很好的起点。@Dave许可证已经更改。它很快就会成为.NETFW的一部分;使用安全@亚伦-太棒了!谢谢你的链接和信息!