2009-06-21 13 views
27

私のアプリでRelayCommandを使用しています。 viewmodelにコードを入れるのにはいいですが、私はコマンドにキーストロークをバインドするにはどうしたらいいですか?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

キーバインドクラスのCommandプロパティはデータバインディングをサポートしていません。この問題は.NET 4.0で解決される予定で、今後の.NET 4.0 Beta 2バージョンではこの問題を確認できるはずです。

+10

.NET 4.0でKeyBindingクラスのCommandプロパティをバインドする方法については、http://tomlev2.wordpress.com/2009/10/26/vs2010-binding-support-in-inputbindings/ –

+1

の記事に記載されています。 http://www.thomaslevesque.com/2009/10/26/vs2010-binding-support-in-inputbindings/ – avenmore

17

私はあなたが記述した理由と同じように、XAMLからはできないと思います。

私はコードビハインドでそれをやった。それはコードですが、コードの単なる行であり、宣言的なものでもありますので、私はそれと一緒に暮らすことができます。しかし、私は本当にこれがWPFの次のバージョンで解決されることを願っています。ここで

は私のプロジェクトの1からコードのサンプル行です:この場合

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

SynchronizeCommandはRelayCommandのインスタンスであり、(明らかに)F9は、それをトリガします。あなたのRoutedCommandsを想定し

-1

は、静的に定義されています。

#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

RouteCommandsではなく、ViewModelでのRelayCommandsに関する疑問。 –

0

を、私は私の見解でキーバインドを作成しますコマンドとキーをリンクするモデル

012その後、
 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項目のコレクションを作成して、私が知っているの後ろにコード内のものを行うために

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

その悪い形の後ろに私の窓のコードでウィンドウのInputBindingsに追加します、しかし、私はバインディングを行う方法をまだ知っていませんが、私はまだそれに取り組んでいます。 :)私に与えるこの唯一のことは、メニュー内の主要なコマンド修飾子リストですが、それは来ています。

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;と同じようにキャストが必要です。 – Ankesh

2

CommandReferenceクラスを使用できます。

とてもエレガントなコードで、魅力的です。

を見てみましょう:それはRelayCommandsと同じように動作しますが、CommandReferenceはあなたが自動CanExecute再評価を達成するために必要なすべてがあるコールCommandManager.RequerySuggested を使用していないので、それはあなたのCanExecutesは更新されませんHow do I associate a keypress with a DelegateCommand in Composite WPF?

をCommandReferenceクラス内で次の変更を行います。