Como selecionar itens do menu Arquivo usando o teclado em WPF e C#?
-
05-07-2019 - |
Pergunta
Estou desenvolvendo um aplicativo WPF UI.
Eu tenho um menu na parte superior da tela, que possui arquivo, ajuda menuitems.
No arquivo -> Recursos de back -end (a tecla de atalho é Ctrl + B), saída (Ctrl + X) itens de menu.
Quando clicado em qualquer item do sub -menu, a janela correspondente é aberta.
Então, sem o uso do mouse, pressionando Ctrl + B ou Ctrl + X, como a janela pode ser aberta?
Além disso, como posso exibir uma pequena linha abaixo do "F" no arquivo para que, quando o usuário pressionar Alt + F, o menu de arquivo deve ser visível.
Estou trabalhando no WPF usando C#.
Solução
Você deseja investigar o ICOMMAND, ROTEDUICOMAND, InputgestureCollection e CommandManager. É um pouco mais de trabalho infraestrutura inicial, mas o padrão de comando WPF permite compartilhar um comando no menu principal, o menu de contexto, os cliques de botão etc. Com suas ações escritas como comandos, todos os lugares do seu aplicativo que usam o comando permitirão /Desative de forma consistente e adicione mais uma camada de indireção para reduzir a repetição do código.
O exemplo a seguir está no vb.net (desculpe, mas espero que seja fácil traduzir).
Implementar cada uma de suas ações necessárias como uma classe que implementa o 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
Crie uma classe que armazena instâncias compartilhadas de cada um de seus comandos.
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
Agora, no seu XAML para o seu menu, você pode vincular a este comando:
<Window.Resources>
<local:MyCommands x:Key="commands"/>
</Window.Resources>
...
<MenuItem Name="mnuOpenWindow" Command="{Binding Path=OpenWindow}"/>
Isso é um pouco mais do que o requisito mínimo de usar comandos, mas em um aplicativo razoavelmente grande, achei essa infraestrutura adicional bastante útil. Depois que os comandos são gravados e registrados, a ligação a eles em qualquer documento XAML é trivial e, ao expor as propriedades compartilhadas para cada ação através da classe MyCommands, você pode acessar os comandos puramente no código, se necessário.
Outras dicas
Para adicionar a pequena linha que representa o acelerador do item de menu, use um sublinhado no XAML:
<MenuItem Header="_File">
<MenuItem Header="_Backend Features" />
<MenuItem Header="E_xit" />
</MenuItem>
Quanto às teclas de atalho, primeiro eu recomendaria não usar Ctrl + X para saída, pois isso geralmente é usado para corte. Normalmente a saída não tem uma tecla de atalho, mas pressionando Alt + F4 Fechar a janela principal terá o mesmo efeito.
Em relação à sua pergunta real, você tem algumas opções, mas para ambos você precisa usar comandos para implementar lidar com seus menuitems em vez do Click
evento.
A primeira opção é definir um InputBinding
Para cada tecla de atalho. Isso seria feito algo assim na sua janela principal:
Para o Command
atributo, você precisaria especificar uma expressão que represente o comando para esse atalho (você usaria o mesmo Command
Ao definir o MenuItem
, também). Se você tem um Commands
Aula, você pode fazer algo como o seguinte:
static class Commands
{
public static ICommand BackendFeaturesCommand = ...;
}
E então em xaml:
<KeyBinding Key="B" Modifiers="Control"
Command="{x:Static Commands.BackendFeaturesCommand}" />
A outra opção é definir seu comando como um RoutedUICommand
, e especificar um InputGesture
para isso. Isso cuidará de conectar a chave de atalho para você.
Você pode dar uma olhada na amostra de shortcutkey do WPF Application Framework (WAF). É bastante simples de entender.