键绑定一个RelayCommand

时间:2009-06-21 13:58:49

标签: wpf mvvm key-bindings

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

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的最佳方法是什么?

6 个答案:

答案 0 :(得分:17)

我认为你不能从XAML那里做到这一点,完全是你描述的原因。

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

以下是我的一个项目的代码示例:

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

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

答案 1 :(得分:14)

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

答案 2 :(得分:10)

您可以继承KeyBinding,添加一个设置Command属性的CommandBinding依赖项属性,然后像任何其他输入绑定一样将其添加到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>

答案 3 :(得分:2)

您可以使用CommandReference类。

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

看看:How do I associate a keypress with a DelegateCommand in Composite WPF?

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

public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}

答案 4 :(得分:0)

我在视图模型中创建了一个Key绑定,它将命令和Key链接起来就像这样

        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;

然后我在我的View Model根目录中创建一个InputBinding项的集合,并将它们添加到我窗口代码中的窗口InputBindings

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

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

答案 5 :(得分:-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>

此致

蒂姆霍顿