Привязка ключа WPF ShortCut к команде в ViewModel

У меня есть приложение WPF, использующее шаблон MVVM. Подключить кнопки к виртуальной машине довольно просто, поскольку они реализуют ICommand. У меня есть контекстное меню, которое работает аналогично. Следующим шагом является создание сочетаний клавиш для контекстного меню. Я не могу понять, как заставить сочетание клавиш вызывать команду. Вот пример:

<MenuItem Header="Update" Command="{Binding btnUpdate}" >
    <MenuItem.Icon>
        <Image Source="/Images/Update.png"
               Width="16"
               Height="16" />
        </MenuItem.Icon>
    </MenuItem>

теперь я добавил это:

<Window.InputBindings>
    <KeyBinding Key="U"
                Modifiers="Control" 
                Command="{Binding btnUpdate}" />
</Window.InputBindings>

чтобы попытаться подключить сочетания клавиш к той же привязке, но это не сработает. Ошибка:

Ошибка 169 «Привязка» не может быть установлена ​​для свойства «Команда» типа «KeyBinding». «Привязка» может быть установлена ​​только для DependencyProperty объекта DependencyObject.

Нет способа связать это событие с Командой? Я не могу понять этого.

заранее спасибо!

Счет


person Bill Campbell    schedule 04.03.2010    source источник
comment
Я должен упомянуть, что я также использую RelayCommand Джоша Смита.   -  person Bill Campbell    schedule 05.03.2010


Ответы (5)


Я написал настраиваемое расширение разметки для "привязки" InputBindings к командам, которые можно использовать почти как настоящую привязку:

<UserControl.InputBindings>
    <KeyBinding Modifiers="Control" 
                Key="E" 
                Command="{input:CommandBinding EditCommand}"/>
</UserControl.InputBindings>

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

Другой вариант - использовать класс CommandReference. Его можно найти в наборе инструментов MVVM, доступном здесь. Это, вероятно, более чистый подход, но немного сложнее в использовании.

Обратите внимание, что в WPF 4 свойства InputBinding.Command, InputBinding.CommandParameter и InputBinding.CommandTarget являются свойствами зависимостей, поэтому их можно связать обычным образом.

person Thomas Levesque    schedule 04.03.2010
comment
Отлично! Это как раз то, что я искал. Спасибо!! - person Bill Campbell; 06.03.2010
comment
Я следил за бывшими в документации WPF MVVM - отличные примеры! Именно то, что я хочу делать. К сожалению, пункты контекстного меню работают нормально, но горячие клавиши ничего не делают. Я даже не могу понять, как это отладить, так как при нажатии сочетаний клавиш ничего не происходит. - person Bill Campbell; 07.03.2010
comment
Может быть, я пытаюсь использовать их для сочетаний клавиш в ContextMenu вместо стандартного меню? - person Bill Campbell; 07.03.2010
comment
какую технику вы использовали? расширение разметки или класс CommandReference? - person Thomas Levesque; 07.03.2010
comment
CommandReference - кажется, имеет значение, где в XAML я помещаю KeyBinding. Если я помещаю его в DataGrid, который находится в окне, я попадаю в точку останова в CanExecute, но, кажется, всегда возвращает false. - person Bill Campbell; 07.03.2010
comment
Я думал, что если я помещу KeyBinding где-нибудь в окне, это сработает, но, похоже, это не так. - person Bill Campbell; 07.03.2010
comment
KeyBinding срабатывает, когда элемент управления, на котором он определен, сфокусирован ... возможно, поэтому это не работает для вас? - person Thomas Levesque; 07.03.2010
comment
Это возможно. Я бы подумал, что если привязка KeyBinding будет помещена в окно, в котором есть элементы управления, она также будет запускаться дочерними элементами управления, но, может быть, нет? - person Bill Campbell; 07.03.2010
comment
Наконец-то он заработал. Просто нужно было разместить KeyBindings и CommandReferences в нужных местах. Не только внутри окна, но и внутри первой сетки. - person Bill Campbell; 08.03.2010

Следующий код можно использовать для привязки сочетания клавиш непосредственно к команде:

<Window.InputBindings>
    <KeyBinding Command="{Binding Path=NameOfYourCommand}" 
                Key="O" 
                Modifiers="Control"/>
</Window.InputBindings>

Добавьте это после Window.Resources в коде XAML вашего представления.

person Michel Keijzers    schedule 19.02.2012
comment
Да, не уверен, в чем была проблема с OP, но это отлично работает. (Я использую свет MVVM) - person GONeale; 08.08.2012
comment
Он специально сказал, что это не сработало, и выбранный ответ объясняет, почему: он не использует WPF4. Не уверен, почему вы публикуете его точный код в качестве ответа - person aaronburro; 13.09.2012
comment
такое Modifiers Ctrl? - person amit jha; 21.05.2017

Я согласен с тем, что делать это в XAML идеально, но для полноты вы также можете добавить свою привязку в код. Если вы делаете это в конструкторе, просто убедитесь, что это после вызова InitializeComponent()

InputBindings.Add(new KeyBinding(btnUpdate, new KeyGesture(Key.U, ModifierKeys.Control));
person Eddie Deyo    schedule 25.05.2010
comment
+1 Этот метод позволил мне разместить его в моем представлении, потому что мне нужно, чтобы функция работала только с элементами пользовательского интерфейса. - person CaptainBli; 04.02.2014
comment
Но это связывает элемент управления "кнопка" btnUpdate с сочетанием клавиш Ctrl-U, а не a с командой, как это делает XAML Мишеля Кейзерса. - person ProfK; 23.10.2014
comment
Я отвечал на исходный пост, который пытался привязать к чему-то под названием btnUpdate. - person Eddie Deyo; 29.10.2014
comment
Это работает, но вам нужно заменить btnUpdate на yourButton.Command. - person EdgarT; 20.09.2015

Альтернативный подход для привязки сочетания клавиш WPF к свойству Command модели ViewModel показан в примере ShortcutKey в WPF Application Framework (WAF).

person jbe    schedule 07.03.2010
comment
Спасибо ... Мне понадобится время, чтобы разобраться в ней (то есть у меня сейчас мало времени, но я проголосовал за, потому что ссылка кажется очень полезной (не только из-за моего вопроса). - person Michel Keijzers; 08.08.2012
comment
Этот ответ предназначен только для пропаганды, он не помогает, как и данная ссылка - person Alessandro Muzzi; 30.05.2019

Смогли добавить привязку клавиш на уровне DataGrid. Нравится :

Xaml:

<DataGrid 
                    AutoGenerateColumns="False"
                    ItemsSource="{Binding YourCollection}"                         
                    CanUserAddRows="False"                        
                    HeadersVisibility="Column" 
                    CanUserDeleteRows="False" 
                    CanUserSortColumns="True"
                    CanUserResizeRows="False"
                    CanUserResizeColumns="False"                       
                    SelectedItem="{Binding YourSelectedItem}" 
                    SelectionMode="Single" 
                    SelectionUnit="FullRow"
                   >
                <DataGrid.ContextMenu>
                    <ContextMenu>
                       **<MenuItem Header="Delete" InputGestureText="Del" Command="{Binding DeleteCommand}">**
                        </MenuItem>
                    </ContextMenu>
                </DataGrid.ContextMenu>
                **<DataGrid.InputBindings>
                    <KeyBinding Key="Delete" Command="{Binding DeleteCommand}" CommandParameter="Delete"/>**
                </DataGrid.InputBindings>
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Column Header" Binding="{Binding YourColumn}" IsReadOnly="True" />
                </DataGrid.Columns>
</DataGrid>

Просмотреть модель:

public ICommand DeleteCommand
            {
                get
                {
                    return new DelegateCommand(ExecuteCommand, CanExecute);
                }
            }

  private void ExecuteCommand()
{
// your code to delete here.
   YourCollection.Remove(YourSelectedItem);
}

private void CanExecute()
{
// logic to check if the delete command can execute.
   return YourSelectedItem != null ;
}
person Tesfay K. Aregay    schedule 08.08.2016