次の方法で共有


方法: ルーティング イベントのクラス処理を追加する

ルーティング イベントは、ルート内の特定のノードのクラス ハンドラーまたはインスタンス ハンドラーのいずれかによって処理されます。 クラス ハンドラーを最初に呼び出し、クラス実装で使用して、インスタンス処理からのイベントを抑制したり、基底クラスによって所有されるイベントに他のイベント固有の動作を導入したりすることができます。 この例は、クラス ハンドラーを実装するための密接に関連する 2 つの手法を示しています。

この例では、Canvas パネルに基づくカスタム クラスを使用しています。 アプリケーションの基本的な前提は、カスタム クラスによって、その子要素に動作が導入されるということです。たとえば、子要素クラスまたはそれに対するインスタンス ハンドラーが呼び出される前に、左マウス ボタンのクリックがインターセプトされ処理済みとしてマークされることなどです。

UIElement クラスによって仮想メソッドが公開され、イベントをオーバーライドするだけで、PreviewMouseLeftButtonDown イベントに対するクラス処理が可能になります。 クラスの階層のどこかでこのような仮想メソッドを使用できる場合、これがクラス処理を実装する最もシンプルな方法です。 次のコードは、Canvas から派生した "MyEditContainer" での OnPreviewMouseLeftButtonDown の実装を示しています。 この実装では、引数でイベントを処理済みとマークし、ソース要素に基本的な目に見える変更を加えるコードを追加します。

protected override void OnPreviewMouseRightButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
    e.Handled = true; //suppress the click event and other leftmousebuttondown responders
    MyEditContainer ec = (MyEditContainer)e.Source;
    if (ec.EditState)
    { ec.EditState = false; }
    else
    { ec.EditState = true; }
    base.OnPreviewMouseRightButtonDown(e);
}
Protected Overrides Sub OnPreviewMouseRightButtonDown(ByVal e As System.Windows.Input.MouseButtonEventArgs)
    e.Handled = True 'suppress the click event and other leftmousebuttondown responders
    Dim ec As MyEditContainer = CType(e.Source, MyEditContainer)
    If ec.EditState Then
        ec.EditState = False
    Else
        ec.EditState = True
    End If
    MyBase.OnPreviewMouseRightButtonDown(e)
End Sub

基底クラスまたはその特定のメソッドで使用できる仮想がない場合は、EventManager クラスのユーティリティ メソッド RegisterClassHandler を使用して、クラス処理を直接追加できます。 このメソッドは、クラス処理を追加しているクラスの静的初期化内でのみ呼び出す必要があります。 この例では、PreviewMouseLeftButtonDown のハンドラーをもう 1 つ追加します。この場合、登録されるクラスはカスタム クラスです。 これに対し、仮想を使用する場合、登録されるクラスは実際には UIElement 基底クラスです。 基底クラスとサブクラスのそれぞれにクラス処理が登録される場合、サブクラス ハンドラーが最初に呼び出されます。 アプリケーションの動作では、最初にこのハンドラーでメッセージ ボックスが表示され、次に仮想メソッドのハンドラーのビジュアルの変更が表示されます。

static MyEditContainer()
{
  EventManager.RegisterClassHandler(typeof(MyEditContainer), PreviewMouseRightButtonDownEvent, new RoutedEventHandler(LocalOnMouseRightButtonDown));
}
internal static void LocalOnMouseRightButtonDown(object sender, RoutedEventArgs e)
{
  MessageBox.Show("this is invoked before the On* class handler on UIElement");
  //e.Handled = true; //uncommenting this would cause ONLY the subclass' class handler to respond
}
Shared Sub New()
    EventManager.RegisterClassHandler(GetType(MyEditContainer), PreviewMouseRightButtonDownEvent, New RoutedEventHandler(AddressOf LocalOnMouseRightButtonDown))
End Sub
Friend Shared Sub LocalOnMouseRightButtonDown(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("this is invoked before the On* class handler on UIElement")
    'e.Handled = True //uncommenting this would cause ONLY the subclass' class handler to respond
End Sub

関連項目