27

我在我的应用程序中使用RelayCommand。将代码放在视图模型中非常棒,但是如何将击键绑定到我的命令?

RoutedUICommand 有它的 InputGestures 属性,当我按下按键时,它会自动调用该命令。(作为一个额外的好处,它甚至可以在 MenuItem 中显示击键。)不幸的是,RoutedUICommand 的额外属性没有可重用的接口,因此我无法制作具有相同魔力的 RelayUICommand。

我已经尝试过使用 InputBindings:

<Window.InputBindings>
    <KeyBinding Key="PageUp" Command="{Binding SelectPreviousLayerCommand}"/>
</Window.InputBindings>

但这给了我一个运行时异常,因为 KeyBinding.Command 不是依赖属性。(实际上,它抱怨的是 KeyBinding 甚至不是 DependencyObject。)由于我的 RelayCommand 是我的 ViewModel 上的一个属性(与 RoutedUICommand 设计的静态字段相反),数据绑定是我知道的唯一方法从 XAML 中引用它。

你们是怎么解决这个问题的?将击键绑定到 RelayCommand 的最佳方法是什么?

4

6 回答 6

17

出于您所描述的原因,我认为您不能从 XAML 执行此操作。

我最终在代码隐藏中完成了它。虽然它是代码,但它只是一行代码,而且还是相当声明性的,所以我可以忍受它。但是,我真的希望在下一版本的 WPF 中解决这个问题。

这是我的一个项目中的示例代码行:

this.InputBindings.Add(new KeyBinding(
    ((MedicContext)this.DataContext).SynchronizeCommand,
    new KeyGesture(Key.F9)));

在这种情况下,SynchronizeCommand 是 RelayCommand 的一个实例,并且(显然)F9 会触发它。

于 2009-06-21T14:47:16.530 回答
14

KeyBinding 类的 Command 属性不支持数据绑定。这个问题将在 .NET 4.0 中得到解决,您应该能够在即将到来的 .NET 4.0 Beta 2 版本中看到它。

于 2009-10-05T11:37:32.190 回答
10

您可以继承 KeyBinding,添加一个CommandBinding设置 Command 属性的依赖项属性,然后像任何其他输入绑定一样将其添加到 XAML。

public class RelayKeyBinding : KeyBinding
{
    public static readonly DependencyProperty CommandBindingProperty =
        DependencyProperty.Register("CommandBinding", typeof(ICommand), 
        typeof(RelayKeyBinding),
        new FrameworkPropertyMetadata(OnCommandBindingChanged));
    public ICommand CommandBinding
    {
        get { return (ICommand)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private static void OnCommandBindingChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var keyBinding = (RelayKeyBinding)d;
        keyBinding.Command = (ICommand)e.NewValue;
    }
}

XAML:

<Window.InputBindings>
    <RelayKeyBinding 
        Key="PageUp" 
        CommandBinding="{Binding SelectPreviousLayerCommand}" />
</Window.InputBindings>
于 2009-09-28T23:45:03.607 回答
2

您可以使用 CommandReference 类。

非常优雅的代码,就像一个魅力。

看一看:如何在 Composite WPF 中将按键与 DelegateCommand 相关联?

它与 RelayCommands 的工作方式相同,但它不会更新您的 CanExecutes,因为 CommandReference 不使用 callCommandManager.RequerySuggested 实现自动CanExecute重新评估所需要做的就是在 CommandReference 类中进行以下更改

public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}
于 2011-04-11T08:05:57.690 回答
0

我在我的视图模型中创建了一个键绑定,它像这样链接命令和键

        this.KeyBinding = new KeyBinding();
        //set the properties
        this.KeyBinding.Command = this.Command;
        this.KeyBinding.Key = this.Key;
        //modifier keys may or may not be set
        this.KeyBinding.Modifiers = this.ModifierKeys;

然后我在我的视图模型根中创建一个 InputBinding 项的集合,并将它们添加到我窗口代码后面的窗口 InputBindings

     foreach (var item in applicationViewModel.InputBindingCollection) {
        this.InputBindings.Add(item);
     }

我知道在后面的代码中做东西的形式不好,但我还不知道如何进行绑定,但我仍在努力。:) 这没有给我的唯一的东西是菜单中的一个关键命令修改器列表,但这即将到来。

于 2009-09-25T00:54:17.993 回答
-1

假设您的 RoutedCommands 是静态定义的:

#region DeleteSelection

    /// <summary>
    /// The DeleteSelection command ....
    /// </summary>
    public static RoutedUICommand DeleteSelection
        = new RoutedUICommand("Delete selection", "DeleteSelection", typeof(ChemCommands));

    #endregion

因此在 XAML 中绑定:

<Canvas.InputBindings>
    <KeyBinding Key="Delete" Command="{x:Static Controls:ChemCommands.DeleteSelection}" />
</Canvas.InputBindings>

问候,

蒂姆·豪顿

于 2009-07-13T14:02:55.690 回答