2009-06-21 55 views
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的最佳方式是什么?

回答

14

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

+10

在http://tomlev2.wordpress.com/2009/10/26/vs2010-binding-support-in-inputbindings/ – 2010-04-20 14:34:48

17

我不认为你可以从XAML做到这一点,因为你描述的原因。

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

下面是从我的项目之一代码示例行:

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

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

-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> 

问候,

蒂姆霍顿

+0

有关ViewModel中的RelayCommands而不是RoutedCommands的问题。 – 2012-06-18 12:46:44

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); 
    } 

它的坏的形式做的东西后面的代码中,我知道,但我不知道如何做绑定,但即时通讯仍在工作。 :)这个东西唯一给我的是菜单中的关键命令修改列表,但即将到来。

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> 
+1

`keyBinding.Command = e.NewValue;`需要一个强制转换,所以它应该像`keyBinding.Command =(ICommand)e.NewValue;`Right? – Ankesh 2011-10-05 08:55:26

2

您可以使用CommandReference类。

非常优雅的代码和作品像一个魅力。

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

它与RelayCommands相同,但由于CommandReference不使用称其将不会更新您CanExecutes CommandManager.RequerySuggested 所有你需要做的,以实现自动CanExecute重新评估是在CommandReference类中执行以下更改

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