Подтвердить что ты не робот

Связывание ключа 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 "Связывание" не может быть задано в свойстве "Command" типа "KeyBinding". "Связывание" может быть установлено только в DependencyProperty объекта DependencyObject.

Нет ли способа подключить это событие к команде? Я не могу понять это.

заблаговременно!

Билл

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

InputBindings.Add(new KeyBinding(btnUpdate, new KeyGesture(Key.U, ModifierKeys.Control));

Ответ 4

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

Ответ 5

Могли добавить Keybinding на уровне 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 ;
}