Data binding 将WPF快捷键绑定到ViewModel中的命令

Data binding 将WPF快捷键绑定到ViewModel中的命令,data-binding,mvvm,shortcuts,Data Binding,Mvvm,Shortcuts,我有一个使用MVVM模式的WPF应用程序。将按钮连接到VM非常简单,因为它们实现了ICommand。我有一个类似的上下文菜单。下一步是为上下文菜单创建快捷键。我不知道如何获得调用该命令的快捷键。以下是一个例子: <MenuItem Header="Update" Command="{Binding btnUpdate}" > <MenuItem.Icon> <Image Source="/Images/Update.png"

我有一个使用MVVM模式的WPF应用程序。将按钮连接到VM非常简单,因为它们实现了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”类型的“Command”属性上设置“Binding”。只能对DependencyObject的DependencyProperty设置“绑定”

是否有办法将此事件连接到命令?我想不出来

提前谢谢

比尔

我写了一个“bind”
InputBindings
命令,它可以像真正的绑定一样使用:

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

请注意,此标记扩展使用私有反射,因此只有在应用程序以完全信任的方式运行时才能使用它

另一个选项是使用
CommandReference
类。可以在可用的MVVM工具包中找到它。这可能是一种更干净的方法,但使用起来有点复杂


请注意,在WPF 4中,
InputBinding.Command
InputBinding.CommandParameter
InputBinding.CommandTarget
属性是依赖性属性,因此它们可以正常绑定

将WPF快捷键绑定到ViewModel的命令属性的另一种方法显示在项目的ShortcutKey示例中。

我同意在XAML中进行绑定是理想的,但为了完整性,您也可以在代码中添加绑定。如果在构造函数中执行此操作,只需确保它位于调用
InitializeComponent()


以下代码可用于将快捷键直接绑定到命令:

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


在窗口之后添加此项。视图的XAML代码中的资源。

已经能够在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>

我应该提到我也在使用Josh Smith的RelayCommand。太棒了!这正是我要找的。非常感谢。我遵循了WPF MVVM文档中的exs-很好的例子!正是我想做的。不幸的是,上下文菜单项可以正常工作,但快捷键没有任何作用。我甚至不知道如何调试它,因为当我按下快捷键时什么都没有发生。可能是因为我试图在上下文菜单而不是标准菜单上的快捷键上使用它们吗?您使用了哪种技术?标记扩展还是CommandReference类?CommandReference?我将KeyBinding放在XAML的何处似乎很重要。如果我把它放在窗口中的DataGrid中,我确实在CanExecute中找到了断点——但它似乎总是返回false。是的,我不确定OP的问题是什么,但这很好。(我使用的是MVVM light)他明确表示这不起作用,选择的答案解释了原因:他没有使用WPF4。不确定你为什么要把他的确切代码作为“答案”贴出来是因为
修饰语
Ctrl
?谢谢。。。我需要一些时间来研究它(这意味着我现在没有太多时间,但我投了更高的票,因为链接似乎非常有用(不仅仅是因为我的问题)。这个答案只是为了宣传,它没有任何帮助,给定的链接+1也没有。这个方法允许我将它放到我的视图中,因为我只需要该函数来处理UI元素。但是这将按钮控件,
btnUpdate
绑定到快捷键Ctrl-U,而不是像Michel Keijzers的XAML那样绑定到命令。我回答了g试图绑定到一个名为“btnUpdate”的东西的原始帖子。这是可行的,但您必须用yourButton.Command替换btnUpdate。
<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 ;
}