インスタンスハンドラーの前に、このクラスのハンドラーがトンネリングイベントの火災に取り付けられないのはなぜですか?

StackOverflow https://stackoverflow.com/questions/9320916

質問

によると このMSDNの記事 (とりわけ)、

ルーティングされたイベントがルートの要素インスタンスに到達するたびに、クラスハンドラーは、そのクラスのインスタンスに接続されているインスタンスリスナーハンドラーの前に呼び出されます。

私はかなり新しいです RoutedEventsしたがって、私は自分のコードに間違いがある可能性がありますが、まるでクラスハンドラーが添付されているようです RoutedEvent それはとして宣言されています RoutingStrategy.Tunnel します いいえ 同じイベントに接続されたインスタンスハンドラーの前に常に発射してください。

以下の私の例では、aを作成しました TouchButton トンネリングを備えた制御クラス RoutedEvent そして泡立ち RoutedEvent. 。それぞれにクラスハンドラーを登録しました。次に、ウィンドウにクラスのインスタンスを作成し、背後のコードの各イベントを処理します。クラス要素と Grid それにはそれが含まれています。 4つのハンドラーはすべて、aに名前を表示します MessageBox したがって、実行の順序をはっきりと見ることができます。

  1. GridインスタンスPreviewTouch
  2. クラスTouchButton_PreviewTouch
  3. TouchButtonインスタンスPreviewTouch
  4. クラスTouchButton_Touch
  5. 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の答えのおかげで、私はすべてのインスタンスハンドラーがイベントの処理を停止する方法を見つけることができました。宣言されたクラス処理タイプのタイプを交換する代わりに TouchButtonGrid Sanguineが示唆したように、私はそれを置き換えます FrameworkElement, 、それからそれはすべてを捕まえます FrameworkElement- 由来するコントロール。

EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent, 
new RoutedEventHandler(TouchButton_PreviewTouch), true);
役に立ちましたか?

解決

MSDNの記事は、トラバースイベントがクラスとインスタンスハンドラーの両方を提供する要素(ツリー)を見つけた場合、インスタンスハンドラーの前にクラスハンドラーを呼び出します。したがって、この場合、イベントが発射され、外出からトンネリングされると、グリッドに遭遇しますが、グリッドクラスにはクラスハンドラーがないため、「グリッド」インスタンスで使用されるインスタンスハンドラーを呼び出すだけです。この行がトグルボタンに追加されている場合 -

eventManager.registerClasshandler(typeof(グリッド)、PreviewTouchevent、新しいRoutedEventHandler(TouchButton_PreviewTouch)、true);

その後、Gridのインスタンスハンドラーの前に、対応するクラスハンドラーが呼び出されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top