インスタンスハンドラーの前に、このクラスのハンドラーがトンネリングイベントの火災に取り付けられないのはなぜですか?
-
26-10-2019 - |
質問
によると このMSDNの記事 (とりわけ)、
ルーティングされたイベントがルートの要素インスタンスに到達するたびに、クラスハンドラーは、そのクラスのインスタンスに接続されているインスタンスリスナーハンドラーの前に呼び出されます。
私はかなり新しいです RoutedEvent
sしたがって、私は自分のコードに間違いがある可能性がありますが、まるでクラスハンドラーが添付されているようです RoutedEvent
それはとして宣言されています RoutingStrategy.Tunnel
します いいえ 同じイベントに接続されたインスタンスハンドラーの前に常に発射してください。
以下の私の例では、aを作成しました TouchButton
トンネリングを備えた制御クラス RoutedEvent
そして泡立ち RoutedEvent
. 。それぞれにクラスハンドラーを登録しました。次に、ウィンドウにクラスのインスタンスを作成し、背後のコードの各イベントを処理します。クラス要素と Grid
それにはそれが含まれています。 4つのハンドラーはすべて、aに名前を表示します MessageBox
したがって、実行の順序をはっきりと見ることができます。
- GridインスタンスPreviewTouch
- クラスTouchButton_PreviewTouch
- TouchButtonインスタンスPreviewTouch
- クラスTouchButton_Touch
- TouchButtonインスタンスタッチ
これは、私が電話した場合を意味します e.Handled = true;
クラスで PreviewTouch
イベントハンドラー、私は実行されたものを除く他のすべてのイベントハンドラーに到達するのを止めることができます Grid
エレメント。これはこのようなものだと思われますか、それともどこかで間違いを犯しましたか?それ以外の場合は、実行が到達するのを止めるにはどうすればよいですか 毎日 インスタンスイベントハンドラー?
これがクラスです:
public class TouchButton : Button
{
static TouchButton()
{
EventManager.RegisterClassHandler(typeof(TouchButton), PreviewTouchEvent,
new RoutedEventHandler(TouchButton_PreviewTouch), true);
EventManager.RegisterClassHandler(typeof(TouchButton), TouchEvent,
new RoutedEventHandler(TouchButton_Touch), true);
}
private static void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_PreviewTouch");
}
private static void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show("Class TouchButton_Touch");
}
public static RoutedEvent TouchEvent = EventManager.RegisterRoutedEvent("Touch",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TouchButton));
public event RoutedEventHandler Touch
{
add { AddHandler(TouchEvent, value); }
remove { RemoveHandler(TouchEvent, value); }
}
public static RoutedEvent PreviewTouchEvent = EventManager.RegisterRoutedEvent(
"PreviewTouch", RoutingStrategy.Tunnel, typeof(RoutedEventHandler),
typeof(TouchButton));
public event RoutedEventHandler PreviewTouch
{
add { AddHandler(PreviewTouchEvent, value); }
remove { RemoveHandler(PreviewTouchEvent, value); }
}
protected override void OnClick()
{
RaiseTouchEvent();
}
private void RaiseTouchEvent()
{
RoutedEventArgs touchEventArgs = new RoutedEventArgs(PreviewTouchEvent);
RaiseEvent(touchEventArgs);
if (!touchEventArgs.Handled) RaiseEvent(new RoutedEventArgs(TouchEvent));
}
}
以下は、ウィンドウコードのインスタンスハンドラーです。
private void TouchButton_PreviewTouch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance PreviewTouch",
((FrameworkElement)sender).Name));
}
private void TouchButton_Touch(object sender, RoutedEventArgs e)
{
MessageBox.Show(string.Format("{0} Instance Touch",
((FrameworkElement)sender).Name));
}
これがコントロールXAMLです:
<Grid Name="Grid" Controls:TouchButton.PreviewTouch="TouchButton_PreviewTouch">
<Controls:TouchButton x:Name="TouchButton" Width="200" Height="45" FontSize="24"
Content="Touch me" Touch="TouchButton_Touch" PreviewTouch="TouchButton_PreviewTouch" />
</Grid>
トンネリングイベントが処理されていることを理解しています Grid
「トンネリング」の前の要素 TouchButton
要素ですが、クラスハンドラーは常にインスタンスハンドラーの前に発射することになっていると思いました。そうでない場合、どうすればこれを達成できますか?
更新>>>
@Sanguineの答えのおかげで、私はすべてのインスタンスハンドラーがイベントの処理を停止する方法を見つけることができました。宣言されたクラス処理タイプのタイプを交換する代わりに TouchButton
と Grid
Sanguineが示唆したように、私はそれを置き換えます FrameworkElement
, 、それからそれはすべてを捕まえます FrameworkElement
- 由来するコントロール。
EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent,
new RoutedEventHandler(TouchButton_PreviewTouch), true);
解決
MSDNの記事は、トラバースイベントがクラスとインスタンスハンドラーの両方を提供する要素(ツリー)を見つけた場合、インスタンスハンドラーの前にクラスハンドラーを呼び出します。したがって、この場合、イベントが発射され、外出からトンネリングされると、グリッドに遭遇しますが、グリッドクラスにはクラスハンドラーがないため、「グリッド」インスタンスで使用されるインスタンスハンドラーを呼び出すだけです。この行がトグルボタンに追加されている場合 -
eventManager.registerClasshandler(typeof(グリッド)、PreviewTouchevent、新しいRoutedEventHandler(TouchButton_PreviewTouch)、true);
その後、Gridのインスタンスハンドラーの前に、対応するクラスハンドラーが呼び出されます。