1

他の情報を持たない関数から返された WPF MenuItem があり、別の (新しい) MenuItem のクリック イベントを最初の MenuItem と同じ関数に設定したいと考えています。

Windows フォームでこれを行うコードを見たことがあります (たとえばIs it possible to "steal" an event handler from one control and give it another? ) が、WPF ルーティング イベントの解決策が見つかりません。

4

1 に答える 1

0

WPF でメニュー項目をコピーする必要がある場合は、推奨されているコマンド パターンを使用しますが、いくつかの巧妙なトリックを使用すれば、イベント ハンドラーもサポートできます (詳細は以下を参照)。アイテムをコピーするために使用するコードは次のようになります。ここで、「アイテム」はコピーしている古い MenuItem です。

MenuItem copy = new MenuItem();
copy.Header = item.Header;
copy.Icon = item.Icon;
copy.Command = item.Command;
copy.CommandParameter = item.CommandParameter;
foreach( CommandBinding binding in item.CommandBindings ) {
    copy.CommandBindings.Add( binding );
}
newCollection.Add( copy );

明らかに、使用する傾向のある MenuItem の機能に応じて、コピーするプロパティを微調整する必要がある場合があります。私はヘッダー、アイコン、およびコマンドにほぼ固執しているので、実装したのはそれだけです。

ここで、イベント ハンドラー スタイルをサポートする必要がある場合は、イベントに割り当てる前に「再生」することしかできないため、何らかの構造の抽象化が必要になります。イベント ハンドラーをメニュー項目に追加すると、それを取得することはほとんどできなくなります。ただし、実際の RoutedEventHandler オブジェクトがある場合 (サブスクリプション前) は、この小さな回避策を実行できます (ここで、「ハンドラー」は、私がラップしている RoutedEventHandler インスタンスです)。

ExecutedRoutedEventHandler executed = (sender, args) =>
{
    RoutedEventArgs innerArgs = new RoutedEventArgs();
    // The consumer probably shouldn't rely on these, but we'll copy them for completeness sake
    innerArgs.RoutedEvent = args.RoutedEvent;
    innerArgs.Handled = args.Handled;
    innerArgs.Source = args.Source;
    handler.Invoke( sender, innerArgs );
};
RoutedUICommand cmd = new RoutedUICommand( "Temp", "Temp", this.GetType() );
newItem.CommandBindings.Add( new CommandBinding(cmd, executed) );
newItem.Command = cmd;

交換が必要かもしれません

this.GetType()

メニュー項目を構築しているコンテキストに応じて、何か他のものを使用します。ビジュアル ツリーで MenuItem の最終的な親になるオブジェクトの型である必要があると思います (私の場合は、コンテキスト メニュー項目をコピーしているオブジェクト)。

于 2011-07-18T16:18:45.913 に答える