2010-08-26 11 views
6

Obecnie używać zdarzenie onKeyDown oraz oświadczenie if/else do tworzenia skrótów klawiaturowych:Wdrożenie Skróty klawiaturowe

if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift && e.Key == Key.Tab) { 

} else if (e.Key == Key.Tab) { 

} ... 

Jednak jeśli mam sporo więcej skrótów klawiaturowych, ten dostaje bałagan.

Czy istnieje lepsza implementacja?

Odpowiedz

17

Należy spojrzeć na realizację <CommandBindings> i <InputBindings>:

<Window.CommandBindings> 
    <CommandBinding Command="Settings" CanExecute="SettingsCanExecute" Executed="SettingsExecuted" /> 
</Window.CommandBindings> 

<Window.InputBindings> 
    <KeyBinding Command="Settings" Key="S" Modifiers="Alt" /> 
</Window.InputBindings> 

Twój <Button> wówczas postać:

<Button Height="50" Width="50" Margin="50,5,0,0" Command="Settings" /> 

Sposób SettingsCanExecute określa, kiedy przycisk jest aktywny i sposób SettingsExecuted jest wywoływana, gdy przycisk jest naciśnięty lub naciśnięta została kombinacja klawiszy.

Następnie nie potrzebujesz obsługi KeyDown.

Istnieje full tutorial w sprawie włączenia kodu. Więcej informacji na temat CommandBindings i InputBindings można znaleźć na stronie MSDN.

+0

hmm ... gdy próbowałem '

+0

Nie jestem pewien, czy coś przegapiłem w samouczku. ale patrząc na kod demo z [John Smith On WPF: Understanding Routed Commands] (http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/) myślę, że muszę utworzyć właściwość na klasa, a następnie odwołaj go w kodzie ... [Snipplet Code Snipplet] (http://snipplr.com/view/39602/cwpf-routed-commands/) –

1

Udokumentowanie tej odpowiedzi dla innych osób, ponieważ jest o wiele prostszy sposób wykonania tego, co rzadko się odwołuje i nie wymaga wcale dotykania XAML.

Aby połączyć skrót klawiaturowy, w konstruktorze Window po prostu dodaj nowe KeyBinding do kolekcji InputBindings. Jako polecenie, przekazuj swoją dowolną klasę poleceń, która implementuje ICommand. W przypadku metody execute wystarczy zaimplementować dowolną logikę, której potrzebujesz. W poniższym przykładzie moja klasa WindowCommand przyjmuje delegata, który wykona za każdym razem, gdy zostanie wywołany. Kiedy skonstruuję nową WindowCommand, aby przekazać moje powiązanie, po prostu wskazuję w moim inicjalizatorze metodę, którą chcę wykonać WindowCommand.

Możesz użyć tego wzoru, aby wymyślić własne szybkie skróty klawiaturowe.

public YourWindow() //inside any WPF Window constructor 
{ 
    ... 
    //add this one statement to bind a new keyboard command shortcut 
    InputBindings.Add(new KeyBinding(//add a new key-binding, and pass in your command object instance which contains the Execute method which WPF will execute 
     new WindowCommand(this) 
     { 
     ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate 
     }, new KeyGesture(Key.P, ModifierKeys.Control))); 
    ... 
} 

Utwórz prostą klasę WindowCommand, która bierze delegata wykonawczego do odpalenia dowolnej ustawionej na nim metody.

public class WindowCommand : ICommand 
{ 
    private MainWindow _window; 

    //Set this delegate when you initialize a new object. This is the method the command will execute. You can also change this delegate type if you need to. 
    public Action ExecuteDelegate { get; set; } 

    //You don't have to add a parameter that takes a constructor. I've just added one in case I need access to the window directly. 
    public WindowCommand(MainWindow window) 
    { 
     _window = window; 
    } 

    //always called before executing the command, mine just always returns true 
    public bool CanExecute(object parameter) 
    { 
     return true; //mine always returns true, yours can use a new CanExecute delegate, or add custom logic to this method instead. 
    } 

    public event EventHandler CanExecuteChanged; //i'm not using this, but it's required by the interface 

    //the important method that executes the actual command logic 
    public void Execute(object parameter) 
    { 
     if (ExecuteDelegate != null) //let's make sure the delegate was set 
     { 
      ExecuteDelegate(); 
     } 
     else 
     { 
      throw new InvalidOperationException("ExecuteDelegate has not been set. There is no method to execute for this command."); 
     } 
    } 
} 
+3

Jedną z podstawowych idei stojących za WPF było uniknięcie konieczności dotykania kod z tyłu. Idealny program WPF/MVVM ma blisko 0 linii kodu. Podczas gdy działa dobrze, nie jest to dobra praktyka. – Christopher

+0

Interesujące. Czy masz na to referencję? Nigdy wcześniej nie widziałem tego w druku, ale jeśli to prawda, dobrze byłoby wiedzieć. Dzięki! –

+0

Każdy pojedynczy przykład nauki dla MVVM, o której wiem, tworzy model widoku. Powoduje utworzenie instancji widoku modelu w XAML. I utrzymuje Kod Behind jako barebones, jak to tylko możliwe. Wszystko, co musisz napisać w kodzie, jest powiązane z tym konkretnym Widok z definicji. A arbitralność poglądu jest podstawową koncepcją w MVVM. Również mój nauczyciel matematyki zwykł mawiać: "Matematycy są leniwymi pisarzami - im więcej piszą, tym więcej mogą popełniać błędy". Stosuję to do pełnego programowania. – Christopher

Powiązane problemy