我正在尝试使用WPF实现“Mega Menu”样式菜单。要查看网页设计中的大型菜单示例,请参阅here。
到目前为止,我尝试使用TextBlocks作为菜单的最高级别创建类似的界面,然后使用鼠标悬停事件显示位于文本块下方的其他窗口。这很麻烦且不灵活,未来的更改需要动态添加/删除TextBlock。
我考虑过使用WPF菜单控件,因为我知道可以大幅修改样式,但我还没有看到任何方法使用Menu控件使用的层次模型生成多列布局。
有更好的方法吗?我是否必须坚持使用自定义窗口和相对定位?有人能指出我已经实施过的一个例子吗?
答案 0 :(得分:1)
您可以使用HeaderedItemsControl并换出Panel
以满足您的需求;默认情况下,它使用StackPanel
,但WrapPanel
可能更适合您。默认情况下,弹出和鼠标悬停行为不存在,需要实现。
更多robust approach将利用自定义Expander;因为它提供了你所追求的弹出行为,并且链接到演练提供了鼠标悬停行为。
答案 1 :(得分:1)
我想知道Ribbon控件是否可以改装来执行此操作?它提供标签,标签,列等等。
请谨慎使用此UI设计,并确保仅在用户明确要求时才打开和关闭。当我正在查看的网站上出现一个弹出的超级菜单时,这是非常烦人的,我不能让它关闭,除非我想点击它并且它消失了。
答案 2 :(得分:1)
您可以使用弹出控件,而不是使用自定义Windows和定位。当用户点击屏幕外,您可以使用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>
使菜单显示在悬停上要困难得多,因为Popups窃取焦点的方式(您可以显示菜单,但如果鼠标悬停在另一个菜单上,则无法轻松隐藏它)。为此,自定义窗口可能会更好。
答案 3 :(得分:0)
自定义窗口和相对位置本质上是WPF Menu / MenuItem控件的工作方式......但是正如您所发现的那样,它非常重要。最好的办法是重新设置Menu / MenuItem控件以满足您的需求。