Comment sélectionner les éléments du menu Fichier à l'aide du clavier dans WPF et C #?
-
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 #.
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.