2009-04-23 4 views
8

J'ai un menu dans wpf qui a une boîte de saisie et un bouton dessus. Une fois que l'utilisateur clique sur le bouton, je dois fermer le menu.Y at-il un moyen de fermer par programme un menuitem dans WPF

Existe-t-il un moyen de le faire?

<Menu x:Name="MainMenu"> 
     <MenuItem Header="Main"> 
      <MenuItem Header="SubMenu" x:Name="SubMenu"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBox Width="50" x:Name="TextBox" /> 
        <Button Content="Click Me and Close" x:Name="Button" IsDefault="True"/> 
       </StackPanel> 
      </MenuItem> 
     </MenuItem> 

Merci, Jon

Répondre

12

Procurez-vous de la MenuItem et faire:

_menuItem.IsSubmenuOpen = false; 

Un moyen facile de mettre la main dessus:

<Button x:Name="_button" Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}, AncestorLevel=2}"/> 

code-behind:

_button.Click += delegate 
{ 
    (_button.Tag as MenuItem).IsSubmenuOpen = false; 
}; 
+1

Cela l'a fait :) Merci! –

3

Je trouve que l'utilisation IsSubmenuOpen n'élimine pas correctement mise au point à partir du menu contenant le MenuItem (surtout si le menu est dans un ToolBar - haut niveau MenuItem reste Selected même si le menu est fermé"). Je trouve l'envoi d'un événement MouseUp au MenuItem fonctionne mieux (en ce bouton, ou de contrôle imbriqué, cliquez sur Gestionnaire d'événements):

 private void button_Click(object sender, RoutedEventArgs e) { 
      Button b = sender as Button; 

      if (b == null || !(b.Parent is MenuItem)) 
       return; 

      MenuItem mi = b.Parent as MenuItem; 

      mi.RaiseEvent(
       new MouseButtonEventArgs(
       Mouse.PrimaryDevice, 0, MouseButton.Left 
      ) 
       {RoutedEvent=Mouse.MouseUpEvent} 
      ); 
     } 
+1

J'ai parcouru le code avec .NET Reflector et Steve a raison. La définition du IsSubmenuOpen laisse une variable interne appelée MenuMode dans un état intermédiaire. L'effet final est que le menu a toujours le focus et que planer au-dessus des en-têtes de menus de haut niveau fera apparaître la liste déroulante. Il semble que l'envoi de l'événement MouseUp réinitialisera correctement les états internes que le contrôle Menu conserve. –

2

Steve merci pour votre solution. C'est en fait une bonne réponse, et enfin quelque chose qui fonctionne vraiment à côté de tonnes de mauvaises réponses sur Internet. J'ai une solution plus courte (et plus sûre) basée sur votre réponse. Étant donné que le parent direct (e.Parent) du bouton n'est pas toujours MenuItem (de la réponse d'origine qui est StackPanel), votre solution ne fonctionnera pas. Il suffit donc de définir la propriété Name du MenuItem (Name = "MyMenuItem") et d'accrocher ce gestionnaire sur le bouton:

private void Button_Click(object sender, RoutedEventArgs e) { 
     MyMenuItem.RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { 
      RoutedEvent = Mouse.MouseUpEvent 
     }); 
    } 
Questions connexes