3

カスタムButtonクラスがあり、クリックされたとき(特定のウィンドウを開いたとき)に常に同じアクションを実行します。通常のボタンのように、ボタンのXAMLで割り当てることができるClickイベントを追加しています。

クリックされたら、Clickイベントハンドラーが割り当てられている場合は実行します。それ以外の場合は、デフォルトのアクションを実行します。問題は、ハンドラーがイベントに追加されているかどうかを確認する方法が明らかにないことです。

イベントのヌルチェックでそれができると思いました:

if (Click == null) 
{ 
    DefaultClickAction(); 
} 
else 
{ 
    RaiseEvent(new RoutedEventArgs(ClickEvent, this));;
}

...しかし、それはコンパイルされません。コンパイラーは、定義クラスの内部でこのチェックを実行しようとしていますが、定義クラスの外部のイベントに対して+=または-=以外は実行できないことを通知します。

私は自分で正しい動作を実装しましたが、それは醜く冗長であり、これを行うための組み込みの方法がないことを信じることができません。私は何かが欠けているに違いありません。

関連するコードは次のとおりです。

public class MyButtonClass : Control
{
    //...

    public static readonly RoutedEvent ClickEvent =
        EventManager.RegisterRoutedEvent("Click",
                                         RoutingStrategy.Bubble,
                                         typeof(RoutedEventHandler),
                                         typeof(MyButtonClass));

    public event RoutedEventHandler Click
    {
        add { ClickHandlerCount++; AddHandler(ClickEvent, value); }
        remove { ClickHandlerCount--; RemoveHandler(ClickEvent, value); }
    }

    private int ClickHandlerCount = 0;

    private Boolean ClickHandlerExists
    {
        get { return ClickHandlerCount > 0; }
    }

    //...
}
4

1 に答える 1

2

いいえ、できません。実際、あなたが持っているコードは、彼らがあなたのコントロール自体でイベントを処理していると想定していますが、あなたは直接ではなくバブルイベントを宣言していますイベントなので、技術的には、要素チェーンのさらに上流でイベントをリッスンすることができます。また、技術的には、イベントをフックするためにCLRイベントを使用する必要はありません。ルーティングされたイベントを直接渡すAddHandlerメソッドを使用するだけで、イベントをチェーンのさらに上位にフックするために誰かが行う必要があります。最後に、誰かがイベントのクラスハンドラーを登録した場合、CLRイベントは使用されません(MyButtonClassのインスタンスに対してそのイベントが発生するたびに通知されます)。UIElement.BuildRouteHelperのようなものを見ると、イベントルートを確立するためにWPFが実行するすべての手順と、イベントが発生したときに呼び出されるオブジェクトが表示されます。

リスナーが存在するかどうかを本当に知る必要がある場合は、ルーティングされたイベントではなく、CLRのみのイベントを作成することをお勧めします。次に、デリゲートがnullでないかどうかを確認できます。

于 2011-10-18T18:55:50.477 に答える