如何让菜单在 WPF 中向左打开? [英] How do get menu to open to the left in WPF?

查看:38
本文介绍了如何让菜单在 WPF 中向左打开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 WPF 中有一个菜单(带有菜单项).不幸的是,当我单击菜单标题时,它会打开右侧的菜单.问题是右边有些东西我不希望它重叠.如何告诉 WPF 打开左侧的菜单?我需要做一个控制模板吗?(对于这种基本的样式更改,控制模板似乎很繁琐).

I have a menu (with menuitems) in WPF. Unfortunately when I click on the menu heading it opens the menu to the right. The problem is that there is stuff on the right that I don't want it to overlap. How do I tell WPF to open the menu to the left? Do I need to do a control template? (control templates seem so heavy handed for such basic style changes).

谢谢!

KSG

推荐答案

虽然您可以像他们一样创建 ControlTemplate 来执行此操作 此处,我同意仅修改 MenuItem 的一部分上的一个值是一种繁琐的方法.相反,我认为这是使用 AttachedProperty 的好地方.我们可以创建类似于 ContextMenuService 的东西,但是对于弹出窗口(事实上,我有点惊讶它没有内置).

While you can create a ControlTemplate to do this like they do here, I agree that it is a cumbersome method just to modify one value on a part of the MenuItems. Instead, I think that this is a great place to use an AttachedProperty. We can create something just like the ContextMenuService, but for Popups (In fact, I'm somewhat surprised that it isn't built in).

要更改弹出窗口的打开位置,我们需要设置弹出窗口的 PlacementMode.我们可以使用 propa 快捷方式生成我们的 AttachedProperty(或属性,如果您想实现其余的).我们需要向我们的 PropertyMetadata 添加一个回调,但是如果在 XAML 中的控件上内联设置了 AttachedProperty,那么回调将在整个控件完全构建之前触发.为了确保 MenuItem 的模板被应用,并且在我们尝试设置它的值之前 Popup 存在,如果它尚未加载,我们可以只附加到 Loaded 事件.加载后,我们希望从模板中检索弹出窗口,如果我们查看 MenuItem 类 我们可以看到它有一个 TemplatePartAttribute,将弹出窗口的名称定义为PART_Popup".一旦我们有了它,我们就可以在 MenuItem 的 Popup 上设置 PlacementMode.

To change where the popup is opening, we're going to want to set the Popup's PlacementMode. We can use the propa shortcut to generate our AttachedProperty(or properties if you want to implement the rest). We need to add a callback to our PropertyMetadata, but if the AttachedProperty is set inline on the control in XAML then the callback will fire before the whole control is fully constructed. To ensure the MenuItem's template is applied, and the Popup exists before we try and set it's value, we can just attach to the Loaded event if it isn't already loaded. Once it is loaded, we want to retrieve the Popup from the template, and if we look at the MenuItem class we can see that it has a TemplatePartAttribute defining the Popup's name as "PART_Popup". Once we have that, we can set the PlacementMode on the MenuItem's Popup.

    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 的位置.

Now that we have our AttachedProperty, it's easy to change the Popup placement in the UI.

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

这篇关于如何让菜单在 WPF 中向左打开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆