Bubbling und Tunneling: Routed Events

Lies in den Artikel rein und unten bekommst Du ein unschlagbares Angebot!

Im Vergleich zu VBA, wo jedes Ereignis für das Steuer-element behandelt wurde, welches es auch ausgelöst hat, gibt es unter WPF einige Erweiterungen. Es gibt dort auch solche Ereignisse, aber in vielen Fällen werden Ereignisse an übergeordnete Elemente weitergeleitet. Das hört sich erstmal so an, als ob man es nicht unbedingt benötigt. Dennoch wollen wir das Prinzip anhand eines Beispiels erläutern, damit Sie mitunter auftretendes unerwartetes Verhalten von Code interpretieren können.

Unter WPF sind Elemente verschachtelt, das heißt, es gibt übergeordnete und untergeordnete Elemente. Das Window-Element ist normalerweise das Hauptelement, welches dann ein Grid enthält, in dem sich wiederum ein Stackpanel mit einer Schaltfläche befinden könnte:

<Window x:Class="BubblingAndTunneling.MainWindow" ... Title="MainWindow" Height="350" Width="525">
     <Grid>
         <StackPanel>
             <Button x:Name="btn" Content="Klick mich!" ... Click="btn_Click"></Button>
         </StackPanel>
     </Grid>
</Window>

Direkte Ereignisse/Direct Events

Wenn der Benutzer nun auf die Schaltfläche namens btn klickt, wird das Ereignis Click ausgelöst, welches üblicherweise durch eine Ereignismethode etwa namens btn_Click implementiert wird:

private void btn_Click(object sender, RoutedEventArgs e) {
     MessageBox.Show("Klick!");
}

Bei dem Click-Ereignis handelt es sich um ein direktes Ereignis. Dieses wird nur von dem Element ausgelöst, für das es implementiert wurde.

Tunneling Events

Bei Tunneling Events handelt es sich um alle Ereignisse, die mit dem Präfix Preview beginnen, also beispielsweise Preview-MouseDown. Was ist die Besonderheit dieser Ereignisse Sie werden immer vom Element der obersten Ebene aus zu den unteren Ebenen abgearbeitet. Wenn Sie also das Ereignis PreviewMouseDown für alle vier Elemente des obigen Beispiels definieren, sieht das wie folgt aus:

<Window x:Class="BubblingAndTunneling.MainWindow" ... Title="MainWindow" Height="350" Width="525" MouseDown="Window_MouseDown" PreviewMouseDown="Window_PreviewMouseDown">
     <Grid MouseDown="Grid_MouseDown" PreviewMouseDown="Grid_PreviewMouseDown" >
         <StackPanel MouseDown="StackPanel_MouseDown" PreviewMouseDown="StackPanel_PreviewMouseDown">
             <Button x:Name="btn" Content="Klick mich!" ... MouseDown="btn_MouseDown" 
                 PreviewMouseDown="btn_PreviewMouseDown"></Button>
         </StackPanel>
     </Grid>
</Window>

Für diese Ereignisse hinterlegen wir die folgenden Methoden (für Debug.WriteLine müssen Sie den passenden Namespace mit using System.Diagnostics hinzufügen):

private void Window_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("Window_PreviewMouseDown");
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("Window_MouseDown");
}
private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("Grid_PreviewMouseDown");
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("Grid_MouseDown");                       
} 
private void StackPanel_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("StackPanel_PreviewMouseDown");
}
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("StackPanel_MouseDown");
}
private void btn_PreviewMouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("btn_PreviewMouseDown");
}
private void btn_MouseDown(object sender, MouseButtonEventArgs e) {
     Debug.WriteLine("btn_MouseDown");
}

Wenn wir nun die Anwendung starten und mit der linken Maustaste auf die Schaltfläche klicken, erhalten wir das Ergebnis aus Bild 1. Es werden also offensichtlich nur die Tunneling-Methoden ausgelöst, also diejenigen, die mit Preview… beginnen.

Es feuert nur die Hälfte der angegebenen Ereignisse.

Bild 1: Es feuert nur die Hälfte der angegebenen Ereignisse.

Immerhin ist hier gut zu erkennen, dass dies ausgehend von der obersten Ebene (Window) bis runter zum Button-Element geschieht. Aber warum werden die MouseDown-Ereignisse nicht ausgelöst

Dies ist wiederum der Fall, wenn wir auf den freien Bereich neben der Schaltfläche klicken. Dann erhalten wir die folgende Ausgabe:

 

Schreibe einen Kommentar