2013-09-04 29 views
10

Ich verstehe, wie Blubbern und Tunneln funktioniert. Allerdings bin ich verwirrt über die Verwendung von ihnen. Hier Deshalb:Wann sind Tunnel- und Bubbling-Ereignisse in WPF nützlich?

ich ein Mausklick-Ereignis behandeln will. Um es zu blasen, gibt es MouseDown und, um es zu tunneln, gibt es PreviewMouseDown. MouseDown bedeutet jedoch nicht unbedingt, dass der Benutzer auf das Steuerelement geklickt hat. Möglicherweise hat der Benutzer den Knopf gedrückt und sich von ihm wegbewegt, um den Klick abzubrechen. Ich möchte nichts ändern, wenn die Schaltfläche nicht angeklickt wird.

Also meine Frage ist, sind, wie die Blubbern/Tunneling Strategien sinnvoll?

Antwort

8

Wenn das Ereignis RoutedEventArgs aufgeführt ist, dann ist es Routingereignis. Routingereignisse unterstützen eine RoutingStrategy von Bubble, Tunnel oder Direct.Schauen wir uns die Event-Handler von Button.Click einen Blick:

private void Grid_Click(object sender, RoutedEventArgs e) 
{ 
    MessageBox.Show("Button Test clicked!"); 
} 

Es RoutedEventArgs angegeben, so ist es Ereignis geführt. Weil die Vorschau nicht im Namen angegeben wurde, daher dieses Bubble-Ereignis. Dies kann auf folgende Weise demonstriert werden:

<Grid ButtonBase.Click="Grid_Click"> 
    <Button Name="TestButton" Width="100" Height="30" Content="Test" /> 
</Grid> 

Wenn Sie auf den TestButton klicken, wird das Ereignis über den Grid steigen wird, und zeigt eine Meldung an:

Knopf-Test geklickt!

Usefulness of Bubbling/Tunneling strategies

Tunneling

Viele der Standardsteuerungen hören Ereignisse, wie KeyDown, MouseDown, etc. Zum Beispiel - DataGrid Kontrolle. Ich möchte durch Drücken der Eingabetaste die Funktion aufrufen einen Datensatz hinzufügen. Aber DataGrid hat bereits KeyDown Ereignis, so dass das Ereignis nicht ausgelöst wird. Sie müssen also Ihre Logik im Ereignis Tunnel tun - PreviewKeyDown, es wird vor dem Ereignis KeyDown funktionieren. Gleiches gilt für RichTextBoxControl.

Bubbling

Manchmal müssen Sie einen globalen Handler für ein bestimmtes Ereignis, so arbeitete sie für alle Bedienelemente in VisualTree. Natürlich, das direkte Ereignis kann man nicht machen. Daher auf der Bühne kommt Bubbling Event.

Ein weiterer Grund ist die Ideologie der WPF. Diese Button kann alles enthalten: Image, eine andere Button, etc:

enter image description here

Der Benutzer auf der TextBlock/Image im Button klicken. Woher wissen wir, dass der Klick in Button war? Das ist richtig, mit Hilfe von Bubbling-Event.

Weitere Informationen finden Sie unter:

Understanding Routed Events and Commands In WPF

Edit

ich wenig ein Click Handler geändert:

private void Grid_Click(object sender, RoutedEventArgs e) 
{ 
    String message = "#" + eventCounter.ToString() + ":\r\n" + 
      " Sender: " + sender.ToString() + ":\r\n" + 
      " Source: " + e.Source + ":\r\n" + 
      " Original Source: " + e.OriginalSource; 

    lstEvents.Items.Add(message); 
} 

Ergebnis Klick auf den Button:

enter image description here

+0

Aber soweit ich weiß, ist Click ein direktes Ereignis und kein Sprudeln. – SanSolo

+1

@SanSolo: Wenn es direkt war, dann wurde die Nachricht 'Button Test angeklickt!' Nicht angezeigt. Wir setzen einen Handler für das 'Grid', nicht für den' Button', und einen Klick auf den 'Button', das Event funktionierte für das' Grid'. Das Ereignis am "Button" ging nach oben und kam zum "Grid". Direct Click Event, soweit ich weiß, war in * 'WinForms' *. –

+1

@SanSolo: Bitte sehen Sie meine Bearbeitung. –

1

Wie Sie sagten, Sie kennen das Konzept der sprudelnden/Tunnelbau so nicht in diese gehen. Aber das ist, was diese Ereignisse beabsichtigt sind, dh sie lassen Sie wissen, ob die Maustaste unten oder oben auf dem Steuerelement oder seinen Kindern war. Ereignisse funktionieren gut. Für Ihr Szenario sollten Sie das Click Ereignis Ihrer Schaltfläche verwenden, die angibt, ob Die Maus war unten und oben auf dem Knopf selbst.

Dank

+0

Klicken wäre ein direktes Ereignis. Meine Verwirrung ist in Bezug auf die Verwendung von Blubbern/Tunneling-Ereignissen – SanSolo

3

Hallo obwohl einige gute Artikel regading dies auf Netz bekommen kann, aber dennoch werde ich versuchen, diese zu beantworten.

Angenommen, Sie einer Taste, um ein sehr einfach Aussehen verleihen ein einzelnes Rechteck aus, und ein einfaches Stück Text als Inhalt liefert Selbst bei einer solchen grundlegenden grafischen Darstellungen, gibt es noch zwei Elemente vorhanden: Der Text und das Rechteck. Die Schaltfläche sollte auf einen Mausklick reagieren, ob sich die Maus über dem Text oder dem Rechteck befindet. Im Standard-.NET-Ereignisbehandlungsmodell würde dies bedeuten, dass für beide Elemente ein MouseLeftButtonUp-Ereignishandler registriert wird.

würde dieses Problem viel schlimmer, wenn die Vorteile der WPF Inhalt Modell nehmen. Eine Schaltfläche ist nicht darauf beschränkt, einfachen Text als Beschriftung zu verwenden. Sie kann ein beliebiges Objekt als Inhalt enthalten. Die XAML unten ist nicht besonders anspruchsvoll, aber auch dies hat sechs sichtbare Elemente: der gelben skizzierten Kreis, die zwei Punkte für die Augen, die Kurve für den Mund, der Text und den Hintergrund der Schaltfläche selbst. Event Handler für jedes einzelne Element anhängen wäre mühsam und ineffizient. Um MouseDown zu arbeiten Wir müssten diesem Code 8 8 MouseDownEvents hinzufügen.

<Button PreviewMouseDown="PreviewMouseDownButton" MouseDown="MouseDownButton"> 
     <Grid PreviewMouseDown="PreviewMouseDownGrid" MouseDown="MouseDownGrid"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <Canvas PreviewMouseDown="PreviewMouseDownCanvas" MouseDown="MouseDownCanvas" Width="20" Height="18" VerticalAlignment="Center"> 
       <Ellipse PreviewMouseDown="PreviewMouseDownEllipse" MouseDown="MouseDownEllipse" x:Name="myEllipse" Canvas.Left="1" Canvas.Top="1" Width="16" Height="16" Fill="Yellow" Stroke="Black" /> 
       <Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" /> 
       <Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" /> 
       <Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" MouseDown="Path_MouseDown_1"/> 
      </Canvas> 
      <TextBlock Grid.Column="1" MouseDown="TextBlock_MouseDown_1">Click!</TextBlock> 
     </Grid> 
    </Button> 

WPF verwendet RoutedEvents Blase/Tunnel/Normal, die als normale Ereignisse eher gründlichere sind. Statt von nur Aufruf-Handler an das Element angebracht, der das Ereignis ausgelöst hat, geht WPF den Baum der Elemente der Benutzeroberfläche, die alle Handler für das Routingereignis zu beliebigen Knoten vom Ursprungselement bis zur Wurzel der Benutzerschnittstelle angebracht Aufruf Baum.

+0

Diese Antwort klärt die Notwendigkeit für Bubbling/Tunneling, das ist der Titel meiner Frage.Allerdings bin ich immer noch verwirrt darüber, warum wir MouseUp oder MouseDown verwenden würden, da es sich hierbei nicht um eine schlüssige Aktion wie Click handelt. MousewheelUp/Down kann ich Szenarien sehen, wo es nützlich ist. Aber im Falle von MouseUp ändern wir etwas, Benutzer bewegt sich weg von der Schaltfläche, es gibt keinen Klick ... wo würden wir es verwenden? – SanSolo