Comment sélectionner les éléments du menu Fichier à l'aide du clavier dans WPF et C #?

StackOverflow https://stackoverflow.com/questions/1405537

  •  05-07-2019
  •  | 
  •  

Question

Je développe une application d'interface utilisateur WPF.

J'ai un menu en haut de l'écran, qui contient Fichier, Aide menus.

Dans le fichier - > Fonctionnalités principales (la touche de raccourci est Ctrl + B), éléments de sous-menu Quitter (Ctrl + x).

Lorsque vous cliquez sur un élément de sous-menu, la fenêtre correspondante s'ouvre.

Alors, sans utiliser la souris, en appuyant sur les touches Ctrl + B ou Ctrl + x, comment ouvrir la fenêtre ??

De plus, comment puis-je afficher une petite ligne sous le "F"? dans le fichier de sorte que lorsque l'utilisateur appuie sur Alt + F, le menu Fichier devrait être visible.

Je travaille sur WPF avec C #.

Était-ce utile?

La solution

Vous voudrez étudier ICommand, RoutedUICommand, InputGestureCollection et CommandManager. L’infrastructure fonctionne un peu plus en amont, mais le modèle de commande WPF vous permet de partager une commande à travers le menu principal, le menu contextuel, les clics sur les boutons, etc. / désactive systématiquement et ajoute une couche d'indirection supplémentaire pour réduire la répétition de code.

L'exemple suivant est en VB.Net (désolé, mais la traduction devrait être facile à traduire).

Implémentez chacune de vos actions requises en tant que classe implémentant ICommand:

Public Class OpenWindowCommand
  Implements ICommand

  Public Function CanExecute(parameter as Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
    'enter code that determines whether this command should be enabled or not
    'if you are listening to some backend logic that changes this state, you can
    'raise a CanExecuteChanged event
  End Function

  Public Sub Execute(parameter as Object) Implements System.Windows.Input.ICommand.Execute
     'code that you want to run for the action
  End Sub
 End Class

Créez une classe qui stocke les instances partagées de chacune de vos commandes.

Public Class MyCommands
  Private Shared ReadyOnly openWindowCmd As ICommand = New OpenWindowCommand()
  Private Shared _openWindow as RoutedUICommand

  Shared Sub New()
    'static constructor
    Dim shortcut = New KeyGesture(Key.W, ModifierKeys.Control)
    RegisterCommand(_openWindow, "OpenWindow", "Open...", shortcut, AddressOf ExecuteOpenWindow, AddressOf CanExecuteOpenWindow)
    'add more commands as needed
  End Sub

  Private Shared Sub RegisterCommand(ByRef command as RoutedUICommand, ByVal name as String, ByVal text as String, ByVal gesture as KeyGesture, ByVal executeHandler as ExecutedRoutedEventHandler, ByVal canExecuteHandler as CanExecuteRoutedEventHandler)
    Dim inputs = New InputGestureCollection()
    If gesture IsNot Nothing Then inputs.Add(gesture)
    command = New RoutedUICommand(text, name, GetType(MyCommands), inputs)
    Dim binding = New CommandBinding(command, executeHandler, canExecuteHandler)
    Application.Current.MainWindow.CommandBindings.Add(binding)
    CommandManager.RegisterClassCommandBinding(GetType(Window),binding)
  End Sub

  Public Shared ReadOnly Property OpenWindow() as RoutedUICommand
    Get
      Return _openWindow
    End Get
  End Property
  Public Shared Sub ExecuteOpenWindow(sender as Object, e as ExecutedRoutedEventArgs)
    openCmd.Execute(e.Parameter)
  End Sub
  Public Shared Sub CanExecuteSave(sender as Object, e as CanExecuteRoutedEventArgs)
    e.CanExecute = openCmd.CanExecute(e.Parameter)
    e.Handled = True
  End Sub

End Class

Maintenant, dans votre XAML pour votre menu, vous pouvez faire appel à cette commande:

<Window.Resources>
  <local:MyCommands x:Key="commands"/>
</Window.Resources>
...
<MenuItem Name="mnuOpenWindow" Command="{Binding Path=OpenWindow}"/>

C'est un peu plus que l'exigence minimale d'utiliser des commandes, mais dans une application assez volumineuse, j'ai trouvé cette infrastructure supplémentaire plutôt utile. Une fois que les commandes sont écrites et enregistrées, leur liaison dans tout document XAML est simple et en exposant les propriétés partagées pour chaque action via la classe MyCommands, vous pouvez accéder aux commandes uniquement en code, si nécessaire.

Autres conseils

Pour ajouter la petite ligne représentant l'accélérateur de l'élément de menu, utilisez un trait de soulignement dans le code XAML:

<MenuItem Header="_File">
    <MenuItem Header="_Backend Features" />
    <MenuItem Header="E_xit" />
</MenuItem>

En ce qui concerne les touches de raccourci, tout d’abord, je vous recommande de ne pas utiliser Ctrl + X pour Exit, car il est généralement utilisé pour Cut. Normalement, exit n'a pas de touche de raccourci, mais appuyer sur Alt + F4 pour fermer la fenêtre principale aura le même effet.

En ce qui concerne votre question, vous disposez de plusieurs options, mais vous devez utiliser des commandes pour implémenter le traitement de vos éléments de menu plutôt que l'événement Click .

La première option consiste à définir un InputBinding pour chaque touche de raccourci. Ce serait fait quelque chose comme ça sur votre fenêtre principale:                   

Pour l'attribut Command , vous devez spécifier une expression représentant la commande associée à ce raccourci (vous utiliserez le même Command lors de la définition du code . > MenuItem également). Si vous avez une classe Commands , vous pouvez effectuer les opérations suivantes:

static class Commands
{
    public static ICommand BackendFeaturesCommand = ...;
}

Et puis en XAML:

<KeyBinding Key="B" Modifiers="Control"
    Command="{x:Static Commands.BackendFeaturesCommand}" />

L’autre option consiste à définir votre commande comme RoutedUICommand , et spécifiez un InputGesture pour cela. Cela vous permettra de câbler la touche de raccourci pour vous.

Vous pouvez consulter l'exemple ShortCutKey du Cadre d'application WPF (WAF) . C'est assez simple à comprendre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top