2009-06-18 54 views
2

我有一个WPF菜单(带menuitems)。不幸的是,当我点击菜单标题时,它会打开右侧的菜单。问题是右边有东西,我不希望它重叠。我如何让WPF打开左侧的菜单?我需要做一个控制模板吗? (对于这种基本的风格变化,控制模板显得如此沉重)。如何让菜单在WPF左侧打开?

谢谢!

KSG

回答

10

虽然你可以创建一个的ControlTemplate做到这一点像他们这样做here,我同意,它只是修改了的MenuItems的一部分的一个值的繁琐方法。相反,我认为这是使用AttachedProperty的好地方。我们可以创建类似ContextMenuService的东西,但对于弹出窗口(事实上,我有点惊讶,它不是内置的)。

要更改弹出窗口的位置,我们要设置Popup的PlacementMode。我们可以使用propa快捷键来生成我们的AttachedProperty(或者如果您想实施其他的属性)。我们需要给我们的PropertyMetadata添加一个回调,但是如果AttachedProperty被设置在XAML中的控件上,那么回调将在整个控件完全构建之前触发。为了确保应用MenuItem的模板,并在弹出窗口存在,然后设置它的值,我们可以将其附加到Loaded事件,如果它尚未加载。 加载后,我们希望从模板中检索Popup,如果我们查看MenuItem class,我们可以看到它有一个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的弹出位置。

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

谢谢。这是诀窍,我喜欢这里使用的一般方法,发布的代码实际上是很好的工作代码。伟大的回应。 – 2009-06-19 19:57:53