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

如何让菜单在WPF中向左打开?,wpf,menu,menuitem,Wpf,Menu,Menuitem,我有WPF中的菜单(带菜单项)。不幸的是,当我点击菜单标题时,它会打开右边的菜单。问题是右边有些东西我不想重叠。我如何告诉WPF打开左边的菜单?我需要做一个控制模板吗?(对于这样的基本样式更改,控件模板似乎过于繁重) 谢谢 KSG虽然您可以像他们那样创建一个ControlTemplate来完成这项工作,但我同意,仅在菜单项的一部分修改一个值是一种麻烦的方法。相反,我认为这是一个使用AttachedProperty的好地方。我们可以创建类似的东西,但是对于弹出窗口(事实上,我有点惊讶它不是内置的)

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

谢谢


KSG

虽然您可以像他们那样创建一个ControlTemplate来完成这项工作,但我同意,仅在菜单项的一部分修改一个值是一种麻烦的方法。相反,我认为这是一个使用AttachedProperty的好地方。我们可以创建类似的东西,但是对于弹出窗口(事实上,我有点惊讶它不是内置的)

要更改弹出窗口的打开位置,我们需要设置弹出窗口的PlacementMode。我们可以使用propa快捷方式来生成我们的(或者,如果您想实现其余的,可以使用属性)。我们需要向PropertyMetadata添加回调,但是如果在XAML中的控件上内联设置了AttachedProperty,那么回调将在整个控件完全构造之前触发。为了确保MenuItem的模板已应用,并且在尝试设置其值之前弹出窗口已存在,如果尚未加载,则可以将其附加到已加载的事件。 加载后,我们希望从模板中检索弹出窗口,如果查看,我们可以看到它有一个TemplatePartAttribute,将弹出窗口的名称定义为“PART_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中更改弹出窗口的位置

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

虽然您可以像他们那样创建一个ControlTemplate来完成这项工作,但我同意,仅在MenuItems的一部分修改一个值是一种麻烦的方法。相反,我认为这是一个使用AttachedProperty的好地方。我们可以创建类似的东西,但是对于弹出窗口(事实上,我有点惊讶它不是内置的)

要更改弹出窗口的打开位置,我们需要设置弹出窗口的PlacementMode。我们可以使用propa快捷方式来生成我们的(或者,如果您想实现其余的,可以使用属性)。我们需要向PropertyMetadata添加回调,但是如果在XAML中的控件上内联设置了AttachedProperty,那么回调将在整个控件完全构造之前触发。为了确保MenuItem的模板已应用,并且在尝试设置其值之前弹出窗口已存在,如果尚未加载,则可以将其附加到已加载的事件。 加载后,我们希望从模板中检索弹出窗口,如果查看,我们可以看到它有一个TemplatePartAttribute,将弹出窗口的名称定义为“PART_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中更改弹出窗口的位置

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


谢谢。这就是诀窍,我喜欢这里使用的一般方法,发布的代码实际上是很好的工作代码。反应很好.tnx;这是最简单的方法谢谢你。这就是诀窍,我喜欢这里使用的一般方法,发布的代码实际上是很好的工作代码。反应很好.tnx;这是最简单的方法