MenuItem の CommandTarget プロパティを何に使用できるか知っている人はいますか? ドキュメントには次のように記載されています。
RoutedCommand で使用する場合、コマンド ターゲットは、Executed イベントと CanExecute イベントが発生するオブジェクトです。CommandTarget プロパティが設定されていない場合、キーボード フォーカスのある要素がターゲットとして使用されます。
ただし、実行時に CommandTarget の値は、コマンドの Execute ハンドラーのどこにも表示されません。sender は、CommandBinding が属するウィンドウです。ExecutedRoutedEventArgs は、メニュー項目の遠い祖先への参照でいっぱいです。
ここでの目標は、さまざまなグリッド、リストなどのさまざまなコンテキスト メニューから実行されるコマンドを実装することです。それらにはすべて、特定のインターフェイスをサポートする項目が含まれています。コンテキスト メニューは異なりますが、共通のコマンドがいくつかあります。「Foo」コマンドは「Foo」を実行するため、共通コマンドは、何をクリックしても、同じ Executed および CanExecute ハンドラを使用します。ハンドラーは、クリックしたグリッド/リストに対して選択されたアイテムが何であるかを判断し、それをインターフェイスにキャストしようとし、そのインターフェイスを持っている場合は何かを行います (特定のコマンドによって消費されるインターフェイスがサポートされていない場合)そのコマンドは無効になります)。ContextMenu または MenuItem を送信者として取得すると、PlacementTarget を取得でき、ユーザーが何をクリックしたかがわかります。ただし、それは ContextMenu の XAML 定義で CommandBinding を定義した場合にのみ機能します。つまり、コマンドが使用されるすべての ContextMenu で XAML のブロック全体をコピーして貼り付け、それらのビュー クラスのすべてでハンドラーを再定義します。 . それは私が維持したい混乱ではありません。
これは、これらのハンドラーを複数回記述したり、各ハンドラーを特定のコマンドに複数回関連付けたりする言語に依存しない理由がない場合のようです。しかし、私が知る限り、XAML はハンドラーとターゲットをまとめてバインドすることを望んでいるようです。ハンドラーを一度バインドしてから、別のターゲットに忍び込むことができますか?
更新: コマンドを静的 Command クラスに配置し、ハンドラーを非静的クラス (メイン ビュー、重要ではない) に配置し、インスタンス化して返す静的 Command.GetCommandBinding(command) メソッドを作成することで、これを解決しました。渡すコマンドの CommandBinding。したがって、グリッド バーでコマンド Foo を使用する場合は、バーが存在するビューのコンストラクターで次のように呼び出します。
Bar.CommandBindings.Add(Commands.GetCommandBinding(Commands.Foo));
次に、コマンドが Bar の ContextMenu に属する MenuItem の Command プロパティに割り当てられると、コマンドの Executed イベントと CanExecute イベントの送信者として Bar が渡されます。
ハンドラーは View クラスのメンバーである必要があるため、XAML でバインディングを実行できません。コマンドの CODE のように、コマンドの NAME を再利用するのを非常に面倒にしながら、設計者がコマンドの NAME を再利用するのにこれほど多くの労力を費やしているのは奇妙に思えます。これは Microsoft がこれまで行った中で最もばかげたことではなく、XAML の残りのほとんどは非常に優れています (IMHO)。
別の解決策: メニュー項目をコンテキスト メニューとは別にリソースとして定義し、メニュー項目全体を再利用します。これは Resources.xaml にあり、マージされた辞書として他の XAML ファイルに含めることができます。イベント ハンドラーは Resources.cs にあります。コンシューマーは、GridContextMenu を使用するか、CtxMenuItem_EmailDocument を同じ方法で独自のコンテキスト メニューに挿入できます。
<MenuItem Command="{x:Static vw:Commands.EmailDocument}"
x:Key="CtxMenuItem_EmailDocument">
<MenuItem.CommandBindings>
<CommandBinding Command="{x:Static vw:Commands.EmailDocument}"
Executed="EmailDocument_Executed"
CanExecute="EmailDocument_CanExecute"
/>
</MenuItem.CommandBindings>
</MenuItem>
<ContextMenu x:Key="GridContextMenu" x:Shared="true">
<!-- other items -->
<StaticResource ResourceKey="CtxMenuItem_EmailDocument" />
<!-- other items -->
</ContextMenu>
CommandTarget は、ボタンに対してまったく異なる動作を示すようです。それか、別のファイルで定義されている場合、またはリソースとして定義されている場合、CommandBindings の動作はまったく異なります。