2010-08-26 2 views
6

Я в настоящее время используют onKeyDown событие и if/else оператор для создания горячих клавиш:Реализовать Keyboard Shortcuts

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

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

} ... 

Однако, если у меня есть достаточно еще несколько сочетаний клавиш, это становится грязно.

Есть ли более эффективная реализация?

ответ

17

Вы должны смотреть на реализацию <CommandBindings> и <InputBindings>:

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

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

Ваш <Button> затем становится:

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

Метод SettingsCanExecute определяет, когда кнопка включена, и метод SettingsExecuted вызывается, когда кнопка или нажата комбинация клавиш.

Вам не нужен обработчик KeyDown.

Включают код. full tutorial.

Более подробную информацию о CommandBindings и InputBindings можно найти на MSDN.

+0

hmm ... когда я попробовал '

+0

Я не уверен, что я пропустил что-либо в учебнике. но глядя на демо-код из [John Smith On WPF: Общие сведения о маршрутизированных командах] (http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/), мне кажется, мне нужно создать свойство на класс затем ссылается на него в коде ... [Snipplr Code Snipplet] (http://snipplr.com/view/39602/cwpf-routed-commands/) –

1

Документирование этого ответа для других, поскольку существует гораздо более простой способ сделать это, на который редко ссылаются, и не требует вообще касаться XAML.

Чтобы связать комбинацию клавиш, в конструкторе Window просто добавьте новый KeyBinding в коллекцию InputBindings. В качестве команды передайте свой произвольный командный класс, который реализует ICommand. Для метода execute просто реализуйте любую логику, в которой вы нуждаетесь. В моем примере ниже мой класс WindowCommand принимает делегата, который он будет выполнять при каждом вызове. Когда я создаю новый WindowCommand для передачи с моей привязкой, я просто указываю в своем инициализаторе метод, который я хочу, чтобы WindowCommand выполнял.

Вы можете использовать этот шаблон, чтобы придумать свои быстрые быстрые сочетания клавиш.

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

Создайте простой класс WindowCommand, который принимает делегата выполнения, чтобы запустить любой установленный на нем метод.

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

Одной из основных идей WPF было избежать необходимости касаться код позади. Идеальная программа WPF/MVVM имеет около 0 строк кода. Хотя он работает отлично, это не очень хорошая практика. – Christopher

+0

Интересно. У вас есть ссылка на это? Я никогда раньше не видел этого в печати, но если это правда, это было бы хорошо знать. Благодаря! –

+0

Каждый пример обучения MVVM, который я знаю, создает модель просмотра. Создает экземпляр этой модели в XAML. И держит Code Behind как баребоны по-человечески. Все, что вам нужно написать в коде, привязано к определенному виду по определению. И произвол взгляда является фундаментальным понятием в MVVM. Также мой учитель математики говорил: «Математики - ленивые писатели - чем больше они пишут, тем больше они могут совершать ошибки». Я применяю это для программирования полностью. – Christopher