2010-08-26 17 views
6

Attualmente uso la manifestazione onKeyDown ed un if/else istruzione per creare scorciatoie da tastiera:Implementare Scorciatoie da tastiera

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

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

} ... 

Tuttavia, se ho un bel po 'di più le scorciatoie da tastiera, questo diventa disordinato.

Esiste un'implementazione migliore?

risposta

17

Si dovrebbe guardare attuare <CommandBindings> e <InputBindings>:

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

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

tuo <Button> diventa quindi:

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

Il metodo SettingsCanExecute determina quando il pulsante è abilitato e il metodo SettingsExecuted viene chiamato quando il pulsante è premuto o la combinazione di tasti ha colpito.

Quindi non è necessario il gestore KeyDown.

C'è uno full tutorial su Accendi il codice.

Ulteriori informazioni su CommandBindings e InputBindings possono essere trovate sul MSDN.

+0

hmm ... quando ho provato '

+0

Non sono sicuro di aver perso qualcosa nel tutorial. ma guardando il codice demo di [John Smith su WPF: Understanding Routed Commands] (http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/) penso di aver bisogno di creare una proprietà su una classe quindi fa riferimento al codice ... [Snipplr Code Snipplet] (http://snipplr.com/view/39602/cwpf-routed-commands/) –

1

Documentare questa risposta per gli altri, poiché esiste un modo molto più semplice per farlo a cui si fa raramente riferimento, e non richiede affatto di toccare XAML.

Per collegare una scelta rapida da tastiera, nel costruttore Finestra è sufficiente aggiungere un nuovo KeyBinding all'insieme InputBindings. Come comando, passa la classe di comando arbitraria che implementa ICommand. Per il metodo execute, implementa semplicemente la logica che ti serve. Nel mio esempio qui sotto, la mia classe WindowCommand accetta un delegato che verrà eseguito ogni volta che viene richiamato. Quando costruisco il nuovo WindowCommand per passare con il mio binding, indico semplicemente nel mio inizializzatore, il metodo che voglio che WindowCommand esegua.

È possibile utilizzare questo modello per creare scorciatoie da tastiera rapide.

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))); 
    ... 
} 

Creare una semplice classe WindowCommand che accetta un delegato di esecuzione per attivare qualsiasi metodo impostato su di esso.

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

Una delle idee principali alla base di WPF era evitare di dover toccare il codice dietro. Il programma WPF/MVVM ideale ha dietro a 0 linee di codice. Mentre funziona bene, non è una buona pratica. – Christopher

+0

Interessante. Hai un riferimento per questo? Non l'avevo mai visto prima in stampa, ma se fosse vero, sarebbe bello saperlo. Grazie! –

+0

Ogni singolo esempio di apprendimento per MVVM che conosco crea un modello di vista. Istanzia il modello di visualizzazione in XAML. E mantiene il codice dietro come barebones quanto umanamente possibile. Tutto ciò che devi scrivere nel codice è legato a quella specifica Visualizza per definizione. E l'arbitrarietà della vista è un concetto fondamentale in MVVM. Anche il mio insegnante di matematica diceva "I matematici sono scrittori pigri - più scrivono, più possono sbagliare". Lo applico alla programmazione completa. – Christopher

Problemi correlati