2

我正在尝试使用 WPF 实现“Mega Menu”样式的菜单。要查看网页设计中的大型菜单示例,请参见此处

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

我考虑过使用 WPF 菜单控件,因为我知道样式可以进行大幅度修改,但是我还没有看到任何方法可以使用菜单控件使用的分层模型生成多列布局。

有一个更好的方法吗?我是否必须坚持使用自定义窗口和相对定位?有人可以指出一个已经实施的例子吗?

4

4 回答 4

1

您可以使用HeaderedItemsControl并换出Panel适合您的需要;默认情况下它使用 aStackPanel但是 aWrapPanel可能更适合您。默认情况下不存在弹出和鼠标悬停行为,需要实现。

强大的方法是利用自定义Expander;因为它提供了您所追求的弹出行为,并且链接到演练提供了鼠标悬停行为。

于 2011-04-04T20:06:35.770 回答
1

我想知道是否可以改装 Ribbon 控件来执行此操作?它提供选项卡、标签、列和所有这些。

请谨慎使用此 UI 设计,并确保它仅在用户明确要求时打开和关闭。当一个弹出式超级菜单出现在我正在查看的网站上时,这是非常烦人的,我无法关闭它,除非我想点击它并且它消失了。

于 2011-04-04T20:29:04.850 回答
1

您可以使用 Popup 控件,而不是使用自定义窗口和定位。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;
    }
}

您需要一种样式来显示它 - 像这样。注意 PART_ 模板部件名称:

<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>

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

于 2011-04-05T00:13:05.093 回答
0

自定义窗口和相对位置本质上是 WPF Menu/MenuItem 控件的工作方式……但正如您所发现的,这并非易事。最好的办法是重新设计 Menu/MenuItem 控件以满足您的需要。

于 2011-04-04T19:54:08.977 回答