アプリで 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にバインドする最良の方法は何ですか?
KeyBindingクラスのCommandプロパティは、データバインディングをサポートしていません。この問題は.NET4.0で解決される予定であり、今後の.NET 4.0 Beta2バージョンで確認できるはずです。
あなたが説明している理由から、XAMLからこれを行うことはできないと思います。
私はコードビハインドでそれを行うことになりました。それはコードですが、それは1行のコードであり、それでもかなり宣言的であるため、私はそれと一緒に暮らすことができます。ただし、これがWPFの次のバージョンで解決されることを心から望んでいます。
これが私のプロジェクトの1つからのコードのサンプル行です:
this.InputBindings.Add(new KeyBinding(
((MedicContext)this.DataContext).SynchronizeCommand,
new KeyGesture(Key.F9)));
この場合のSynchronizeCommandはRelayCommandのインスタンスであり、(明らかに)F9がそれをトリガーします。
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>
CommandReferenceクラスを使用できます。
非常にエレガントなコードで、魅力のように機能します。
以下をご覧ください: コンポジットWPFでキー押下をDelegateCommandに関連付けるにはどうすればよいですか?
これはRelayCommandsでも同じように機能しますが、CommandReferenceは呼び出しCommandManager.RequerySuggested
を使用しないため、CanExecutesは更新されません。自動CanExecute
再評価を実現するために必要なのは、内部で次の変更を行うことだけです。 CommandReferenceクラス
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
コマンドとキーをリンクするキーバインディングをビューモデルに作成します。
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);
}
私が知っている背後のコードで何かをするのは悪い形ですが、バインディングを行う方法はまだわかりませんが、まだ取り組んでいます。 :)このdoentが私に与える唯一のものは、メニューのキーコマンド修飾子リストですが、それは来ることです。