Warum ist dieser Klassenhandler vor einem Instanz -Handler nicht an einem Tunnelereignis angeschlossen?

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

Frage

Entsprechend Dieser MSDN -Artikel (unter anderen),

Klassenhandler werden vor einem Instanz -Hörer -Handler aufgerufen, der an eine Instanz dieser Klasse angeschlossen ist, wenn ein Routed -Ereignis in seiner Route eine Elementinstanz erreicht.

Ich bin ziemlich neu in RoutedEvents also besteht die Möglichkeit, dass ich einen Fehler in meinem Code habe, aber es scheint, als ob ein Klassenhandler an a angehängt wäre RoutedEvent das wird als als deklariert als als RoutingStrategy.Tunnel tut nicht Feuern Sie immer vor den Instanzhandlern, die an dasselbe Ereignis angeschlossen sind, vor.

In meinem Beispiel unten habe ich a erstellt TouchButton Kontrollklasse mit einem Tunneling RoutedEvent und ein sprudelnder RoutedEvent. Ich habe für jeden Klassenhandler registriert. Ich habe dann eine Instanz der Klasse in einem Fenster erstellt und jedes Ereignis im Code dahinter verarbeitet. Ich habe den gleichen Handler für das Tunneling -Ereignis sowohl auf dem Klassenelement als auch auf dem angehängt Grid das enthält es. Alle vier Handler zeigen ihren Namen in einem an MessageBox Sie können also deutlich die Ausführungsreihenfolge sehen.

  1. Grid Instance Previewtouch
  2. Klasse Touchbutton_PreviewTouch
  3. Berührungsbutton -Instanz Previewtouch
  4. Klasse Touchbutton_touch
  5. Berührungsstreicher Instanz Touch

Das bedeutet, dass, wenn ich anrufe e.Handled = true; in der Klasse PreviewTouch Event -Handler kann ich ausführen, alle anderen Event -Handler zu erreichen, mit Ausnahme der, die dem angeschlossen ist Grid Element. Soll das so sein oder habe ich irgendwo einen Fehler gemacht? Wie kann ich ansonsten verhindern, dass die Ausführung erreicht? jeder Instanzereignis Handler?

Hier ist die Klasse:

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));
    }
}

Hier sind die Instanzhandler im Fenstercode dahinter:

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));
}

Hier ist die Kontrolle 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>

Ich verstehe, dass das Tunnelereignis von der behandelt wird Grid Element vor "Tunneln" bis zur TouchButton Element, aber ich dachte, dass die Klassenhändler immer vor den Instanzhandlern abfeuern sollten. Wenn nicht, wie kann ich das erreichen?

Update >>>

Dank der Antwort von @sanguines habe ich es geschafft, einen Weg zu finden, alle Instanzhandler davon abzuhalten, die Veranstaltung zu bewältigen. Wenn anstatt die deklarierte Art von Klassenhandhabung zu ersetzen TouchButton mit Grid Wie Sanguine vorschlug, ersetze ich es durch FrameworkElement, dann wird es alles fangen FrameworkElement-Elendes Kontrollen.

EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent, 
new RoutedEventHandler(TouchButton_PreviewTouch), true);
War es hilfreich?

Lösung

MSDN -Artikel bedeutet - Wenn ein Durchqueren eines Ereignisses ein Element (im Baum) findet, das sowohl der Klasse als auch des Instanzhandlers vorliegt, ruft er vor dem Instanz -Handler den Klassenhandler auf. Daher trifft es in diesem Fall, wenn das Ereignis abgefeuert und von Out nach IN abgefeuert wird, auf Raster, aber die Grid -Klasse hat keinen Klassenhandler, sodass er lediglich den Instanz -Handler aufruft, der von der "Raster" -Instanz verwendet wird. Wenn diese Zeile in der Schaltfläche "Schalter" hinzugefügt wird.

EventManager.registerClassHandler (Typof (typeof (Netz), PreviewtouchEvent, New RouteDEventHandler (touchbutton_previewtouch), true);

Dann wird der entsprechende Klassenhandler vor dem Instanzhandler von Grid aufgerufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top