2009-06-21 54 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; } 
}