如何在WPF中使菜单向左打开?

3

我在WPF中有一个带有菜单项的菜单。不幸的是,当我点击菜单标题时,它会向右打开菜单。问题是右侧有一些我不想重叠的东西。我该如何告诉WPF将菜单向左打开?我需要做控件模板吗?(对于如此基本的样式更改,控件模板似乎太过繁琐了)。

谢谢!

KSG

1个回答

15
虽然你可以像这里 这样 创建一个 ControlTemplate 来实现,但我认为这种方法修改菜单项的一个值有些繁琐。相反,我认为这是使用附加属性的好地方。我们可以创建类似于ContextMenuService的东西,但用于弹出式菜单(事实上,我有点惊讶它没有被内置)。
要更改弹出窗口打开的位置,我们需要设置 Popup 的 PlacementMode。我们可以使用 propa 快捷方式来生成我们的附加属性(或者如果您想要实现其他功能也可以生成属性)。我们需要在 PropertyMetadata 中添加回调,但如果在 XAML 中行内设置了附加属性,则回调将在整个控件完全构建之前触发。为确保 MenuItem 模板已应用并且 Popup 存在于我们尝试设置其值之前,我们可以仅在未加载时附加到 Loaded 事件。
一旦它被加载,我们就想从模板中检索 Popup,如果查看MenuItem 类,我们可以看到它具有一个 TemplatePartAttribute,将 Popup 的名称定义为 "PART_Popup"。有了这个,我们就可以在 MenuItem 的 Popup 上设置 PlacementMode。
    public static PlacementMode GetMenuPlacement(DependencyObject obj)
    {
        return (PlacementMode)obj.GetValue(MenuPlacementProperty);
    }

    public static void SetMenuPlacement(DependencyObject obj, PlacementMode value)
    {
        obj.SetValue(MenuPlacementProperty, value);
    }

    // Using a DependencyProperty as the backing store for MenuPlacement.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MenuPlacementProperty =
        DependencyProperty.RegisterAttached("MenuPlacement",
        typeof(PlacementMode),
        typeof(Window1),
        new FrameworkPropertyMetadata(PlacementMode.Bottom, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnMenuPlacementChanged)));

    private static void OnMenuPlacementChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var menuItem = o as MenuItem;
        if (menuItem != null)
        {
            if (menuItem.IsLoaded)
            {
                SetPopupPlacement(menuItem, (PlacementMode)e.NewValue);
            }
            else
            {
                menuItem.Loaded += new RoutedEventHandler((m, v) => SetPopupPlacement(menuItem, (PlacementMode)e.NewValue));
            }
        }
    }

    private static void SetPopupPlacement(MenuItem menuItem, PlacementMode placementMode)
    {
        Popup popup = menuItem.Template.FindName("PART_Popup", menuItem) as Popup;
        if (popup != null)
        {
            popup.Placement = placementMode;
        }
    }

现在我们有了AttachedProperty,很容易在UI中更改Popup的位置。

<Menu>
    <MenuItem Header="Item 1"
              local:Window1.MenuPlacement="Right">
        <MenuItem Header="SubItem 1" />
        <MenuItem Header="SubItem 2" />
        <MenuItem Header="SubItem 3" />
        <MenuItem Header="SubItem 4" />
    </MenuItem>
    <MenuItem Header="Item 2"
              local:Window1.MenuPlacement="Left">
        <MenuItem Header="SubItem 5" />
        <MenuItem Header="SubItem 6" />
        <MenuItem Header="SubItem 7" />
        <MenuItem Header="SubItem 8" />
    </MenuItem>
    <MenuItem Header="Item 3"
              local:Window1.MenuPlacement="Mouse">
        <MenuItem Header="SubItem 9" />
        <MenuItem Header="SubItem 10" />
        <MenuItem Header="SubItem 11" />
        <MenuItem Header="SubItem 12" />
    </MenuItem>
</Menu>

谢谢。这就是诀窍,我喜欢这里使用的通用方法,而且发布的代码实际上是有效的工作代码。非常好的回复。 - Kang Su
谢谢;这是最简单的方法。 - david2020

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接