2011-12-23 12 views
5

すべてのメニュー/ contextmenus /ツールバーはかなりこのようにViewModelにコード内で宣言されています「純粋な」MVVMのMenuItemキーボードショートカット?私は、WPFで使用

MenuService.Add(new MenuItem() 
    { 
    Header = "DoStuff", 
    Command = new relayCommand(DoStuff,() => CanDoStuffExecute()) 
    // some more properties like parent item/image/... 
    }); 

MenuServiceは、MenuItemのの階層リストであり、実際のメニューのにバインドされます単一の結合ポイントを提供しますItems xamlのソース。

これは非常にうまくいきましたが、同じように便利な方法でキーボードショートカットを追加したいと思います。 理想のMenuItemはので、私は単に項目のコマンドにつながる

Shortcut = new KeyGesture(Key.D, ModifierKeys.Control) 

はメニューを所有するウィンドウでCtrl + Dを押す時に呼び出されて書くことができるタイプSystem.Windows.Input.KeyGestureの財産になるだろう、とこれも希望メニューに「Ctrl + D」と表示されます。

私はここで失われています:私は、データバインディングを介してMenuItem.InputBindingsコレクションを設定したいが、取得専用です。とにかくアイテムをどうやって入手できますか?または、既にこのようなものをサポートしているMVVMフレームワークはありますか?ほとんどのq &はキーボードショートカットにありますが、xamlを使ってショートカットを設定するのは助けにはなりません。 「routeduicommand対relaycommandと 『relaycommand keygesture』などの検索

更新

はハックソリューションしかし、作業を考え出すのに十分な情報を明らかにしました。間違いなくそこに他のより良い方法がありますが、現時点ではこれは私にとって非常に低い優先事項であり、仕事を完璧にしています。私はこのようなMenuItemクラスに2つのプロパティを追加しました:

//Upon setting a Gesture, the original command is replaced with a RoutedCommand 
//since that automatically gives us proper display of the keyboard shortcut. 
//The RoutedCommand simply calls back into the original Command. 
//It also sets the CommandBinding property, which still has to be added to the 
//CommandBindingCollection of either the bound control or one of it ancestors 
public InputGesture Gesture 
{ 
    set 
    { 
    var origCmd = Command; 
    if(origCmd == null) 
     return; 
    var routedCmd = new RoutedCommand(Header, 
     typeof(System.Windows.Controls.MenuItem), 
     new InputGestureCollection { value }); 
    CommandBinding = new CommandBinding(routedCmd, 
     (sender, args) => origCmd.Execute(args.Parameter), 
     (sender, args) => { args.CanExecute = origCmd.CanExecute(args.Parameter); }); 
    Command = routedCmd; 
    } 
} 

//CommandBinding created when setting Gesture 
public CommandBinding CommandBinding { get; private set; } 

だから、これは(すなわち、それらは等を簡単に設定されているコード内のキーボードショートカットを追加する)私はもともとを求めた機能を提供します。コマンドバインディングを登録するだけです。現時点では、これらのすべてをApplication.Current.MainWindow.CommandBindingsに追加するだけで完了します。

答えて

3

これは実際には「回答」(私は明らかにコメントを追加することはできません)の資格はありませんが、あなたがやっていることはWPFの意図した方法ではないことを示唆しています。これをWindows Formsのやり方(そして他の多くのツールキットのように)で行い、コードであなたのUXを定義します。あなたが行った限りでは、レンガの壁にぶつかりました。キーのジェスチャーは純粋にUXであり、コードビハインドでは明確に指定することはできません。 (ビューモデルの機能としての)外観と、それとのユーザーのやりとり(特定のコマンドを実行する方法)は、XAML定義のためのものです。

プロパティ値とコマンドはビューモデルのため、このビューモデルを他のビューに再利用し、簡単にユニットテストを作成することができます。ビューモデルでキーボードショートカットを実装することで、どのようにテスト容易性が向上しますか?また、他のビューで使用するには、実際のショートカットが新しいビューには適用されない可能性があるので、そのビューがそれらの所属ではないと主張することができます。他にも理由があるかもしれませんが、XAMLでこれらを定義することを検討することをお勧めします。

-Addedは、あなたのCOMMENT-

に応じて、あなたはかなり右だ - と私は任意のコードや不必要鈍角巻き上げを避けるために懸命に試みたいくつかのかなり大きなWPF UXのプロジェクトを見てきました。私はどちらのアプローチでも作業結果が得られるようにしようとしていますが、私が得ることができるほど簡単です。

ここでは、単にMenuItemを作成するサンプルスニペットを示します。

<Menu x:Name="miMain" DockPanel.Dock="Top"> 
    <MenuItem Command="{Binding Path=MyGreatCommand}" Header="DoSomething"/> 

これでメニューが作成されます。ここでは、MyGreatCommandICommandで、単にビューモデルのプロパティです。あなたはすでに答えと見つけた唯一のXAML検索したことに言及したので、私は一般的に、しかし

<Window.InputBindings> 
    <KeyBinding Key="X" Modifiers="ALT" Command="{Binding Path=MyGreatCommand}"/> 

...キージェスチャーを割り当てるには

など、DockPanel内、StatusBarを処理するために、その場所 - 私はあなたがすでにこのアプローチを試したことを前提としています。私は、ユーザ定義のICommandの代わりにRoutedUICommandを使用しました。ヘッダーテキストにその右寄せのキージェスチャを得るには、両方を行う方法が見つかりませんでした。コマンドとキージェスチャーをコードで作成することを主張する場合は、RoutedUICommandを作成する必要があります。

なぜXAML以外のキージェスチャーを設定したいのですか?

あなたは、特定の状態があなたのビューモデル内で揺れを保持する場合にのみ表示されるように、いくつかのメニュー項目をしたい場合は、あなたがCollapsedまたはVisibleに(他のメニュー項目を含めることができます)メニュー項目のVisibilityプロパティをバインドすることができます。

+0

いくつかのコードサンプルを提供できますか?私はxamlで完全なメニューを定義するべきですか?または単にショートカットですか?私はどのように見たいのですか?プラグインがサブメニューを自由に追加できるグローバルな 'ツール'メニューのようなものが必要です - xamlでもできますか?またそれを行うことができます、それはちょっとxamlでコードを捨てるでしょうか?今私はメニューコマンドを追加する必要があるように、コードが表示されます。それは得ることができるように短く、便利であり、それはbeatifully働く。 Btwのレンガ壁は2つの方向で機能します:私はまだ、UXの部分がコードで定義されていない大規模なアプリケーションを見なければなりません。それは神話です。 – stijn

+0

あなたは本当に正しいです。私は、コードを避けようとするのは本当に大変だったWPF UXプロジェクトを見てきました。私はちょうどどちらの方法でも簡単に使えるようにしようとしています。 ここにサンプルスニペットがあります(中国人の不在を赦してください - 私はこのウェブサイトでこれをどのようにフォーマットするのか不明です)。 '

JamesWHurst

+1

editあなたの答えは、コードを貼り付け、それを選択し、*コードサンプル*ボタンをクリックしてください。 – stijn

関連する問題