方法 : ルーティング イベントのクラス処理を追加する
ルーティング イベントは、クラス ハンドラーまたはルート内の特定のノードにあるインスタンスで処理できます。 クラス ハンドラーが最初に呼び出され、このクラス ハンドラーをクラス実装が使用してインスタンス処理からのイベントの出力を抑制したり、基本クラスが所有するイベントに他のイベント固有の動作を導入できます。 次の例では、クラス ハンドラーを実装するための、非常に密接に関連する 2 つの手法を示します。
使用例
この例では、Canvas パネルに基づくカスタム クラスを使用します。 子要素クラスまたはその上にあるインスタンス ハンドラーが呼び出される前に、左のマウス ボタンのすべてのクリックをインターセプトし、それらを処理済みとしてマークするなど、カスタム クラスがその子要素に動作を導入していることが、アプリケーションの基本前提になります。
UIElement クラスは、PreviewMouseLeftButtonDown イベントを単純にオーバーライドして、そのイベントでクラス処理を有効にする仮想メソッドを公開します。 これは、仮想メソッドがクラスの階層内のどこかで使用できる場合の、最も単純なクラス処理の実装方法です。 次のコードは、Canvas から派生した "MyEditContainer" での OnPreviewMouseLeftButtonDown の実装を示します。 この実装では、引数でイベントを処理済みとしてマークしてから、ソース要素に基本的な表示変更を与えるコードを追加します。
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
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);
}
基本クラスまたはその特定のメソッドに対して仮想メソッドが使用できない場合、クラス処理は EventManager クラスのユーティリティ メソッド RegisterClassHandler を使用して直接追加できます。 このメソッドは、クラス処理を追加しているクラスの静的な初期化内でのみ呼び出す必要があります。 この例では、PreviewMouseLeftButtonDown の別のハンドラーを追加します。この場合、登録済みのクラスがカスタム クラスになります。 これに対し、仮想メソッドを使用している場合は、登録済みのクラスは実際に UIElement の基本クラスになります。 基本クラスとサブクラスがそれぞれクラス処理を登録している場合、サブクラスのハンドラーが最初に呼び出されます。 この場合のアプリケーションの動作は、まずこのハンドラーにそのメッセージ ボックスが表示されてから、仮想メソッドのハンドラーのビジュアルな変更が示されます。
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
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
}