2009-06-18 5 views
2

J'ai un menu (avec menuitems) dans WPF. Malheureusement, lorsque je clique sur l'en-tête du menu, il ouvre le menu vers la droite. Le problème est qu'il y a des choses à droite que je ne veux pas qu'elles se chevauchent. Comment puis-je dire à WPF d'ouvrir le menu à gauche? Ai-je besoin de faire un modèle de contrôle? (les modèles de contrôle semblent si lourds pour de tels changements de style de base).Comment faire pour ouvrir le menu à gauche dans WPF?

Merci!

KSG

Répondre

10

Alors que vous pouvez créer un ControlTemplate pour le faire comme ils le font here, je suis d'accord qu'il est une méthode lourde juste pour modifier une valeur sur une partie des MenuItems. Au lieu de cela, je pense que c'est un bon endroit pour utiliser un AttachedProperty. Nous pouvons créer quelque chose comme le ContextMenuService, mais pour Popups (En fait, je suis un peu surpris qu'il ne soit pas intégré).

Pour changer l'endroit où le popup s'ouvre, nous allons vouloir définir le PlacementMode du Popup. Nous pouvons utiliser le raccourci propa pour générer notre AttachedProperty (ou les propriétés si vous voulez implémenter le reste). Nous devons ajouter un rappel à notre propriété PropertyMetadata, mais si la propriété AttachedProperty est définie en ligne sur le contrôle en XAML, le rappel se déclenchera avant que le contrôle entier ne soit entièrement construit. Pour assurer le modèle de MenuItem est appliqué, et le Popup existe avant d'essayer de régler sa valeur, nous pouvons simplement joindre à l'événement Loaded si elle est pas déjà chargé. Une fois qu'il est chargé, nous voulons récupérer le Popup à partir du modèle, et si nous regardons le MenuItem class nous pouvons voir qu'il a un TemplatePartAttribute définissant le nom du Popup comme « PART_Popup ». Une fois que nous avons cela, nous pouvons définir le PlacementMode sur le Popup MenuItem.

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

Maintenant que nous avons notre AttachedProperty, il est facile de changer la mise en place de Popup dans l'interface utilisateur.

<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

Merci. Cela ne l'affaire et j'aime la méthode générale utilisée ici et le code affiché est en fait un bon code de travail. Bonne réponse. –

Questions connexes