Warum klicken Sie nicht auf das Ereignis „Bubble Up Visual Tree“ zu Stackpanel, wie der Artikel von MSDN heißt?

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

  •  20-08-2019
  •  | 
  •  

Frage

Im MSDN -Artikel Verständnis von Routed -Ereignissen und -befehlen in WPF, Es sagt aus

Ein Ereignis sprudelt (verbreiten) den visuellen Baum aus dem Quellelement, bis es entweder gehandhabt wurde oder das Wurzelelement erreicht.

In diesem Beispiel klicken Sie jedoch auf die Schaltfläche, wenn Sie auf die Schaltfläche klicken. Es "sprudelt den visuellen Baum nicht", um vom Eltern -Stackpanel -Event behandelt zu werden, IE, das auf die Schaltfläche klickt, feuert keine Veranstaltung aus.

Warum nicht? Was meinst sie dann mit "sprudeln" Wenn nicht das?

Xaml:

<Window x:Class="TestClickEvents456.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel x:Name="TheStackPanel"
                Background="Yellow"
                MouseDown="TheStackPanel_MouseDown">
        <Button x:Name="TheButton"
                Margin="10"
                Content="Click This"/>
        <TextBlock x:Name="TheMessage"
                   Text="Click the button or the yellow area"/>
    </StackPanel>
</Window>

Code-Behind:

using System.Windows;
using System.Windows.Input;

namespace TestClickEvents456
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void TheStackPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            TheMessage.Text = "StackPanel was clicked.";
        }

    }
}
War es hilfreich?

Lösung

Die Veranstaltung sprudelt, bis es gehandhabt wird ...

Da die Schaltfläche mit Ihren Mausklicks etwas tut, absorbiert sie Ihr Mausereignis und verwandelt es in ein Clickevent.

Wenn Sie die PreviewMouseDown verwenden, sehen Sie, dass das Stackpanel das Ereignis zuerst erhält, bevor die Schaltfläche der Schaltfläche tut. Vorschau -Ereignisse verwenden den Tunnel -Down -Ansatz.

Andere Tipps

Wie andere gesagt haben, liegt es daran, dass die MouseDown Ereignis wird von der behandelt Button Bevor es weiter sprudelt werden kann. Sie können dies in Reflektor sehen, in ButtonBase.OnMouseLeftButtonDown:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
    if (this.ClickMode != ClickMode.Hover)
    {
        e.Handled = true;
        // SNIP...
    }
    base.OnMouseLeftButtonDown(e);
}

Eine Lösung besteht darin, auf a zuzuhören MouseDown Ereignis und geben Sie an, dass es Ihnen egal ist, ob die Veranstaltung behandelt wird. Sie können dies mit dem tun AddHandler Methode. Es hat eine Boolesche Überladung, mit der Sie auf bereits gehandhabte Ereignisse zuhören können.

Wenn Sie dies irgendwo tun, anstatt den MouseDown -Handler in XAML zu setzen:

TheStackPanel.AddHandler(MouseDownEvent, new MouseButtonEventHandler(TheStackPanel_MouseDown), true);

Sie erhalten alles MouseDown Ereignisse auf TheStackPanel, unabhängig davon, ob sie gehandhabt wurden.

Wenn Sie möchten, dass das Stackpanel die Veranstaltung erhält, ändern Sie die Stackpanel XAML in:

<StackPanel x:Name="TheStackPanel" 
            Background="Yellow"
            Button.Click="TheStackPanel_MouseDown" />

und die Ereignissignatur zu:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e)

In diesem Fall erhalten das Stackpanel das Klickereignis der Schaltfläche. Wenn Sie jedoch auf das Stackpanel selbst klicken, wird kein Ereignis abgefeuert, da es speziell auf eine Schaltfläche klickt.

Es liegt daran, dass alle Nachrichten erfasst werden abgewickelt durch Schaltfläche und Nachrichten stoppen Die Nachricht stoppt dort sprudeln. Die Antwort ist im Text Ihrer Frage richtig:

Ein Ereignis wird aus dem Quellelement den visuellen Baum ausbreiten (ausbreiten) Bis es beide behandelt wurde oder es erreicht das Wurzelelement.

BEARBEITEN:

Edward Tanguay (OP) kommentierte diese Antwort und ich kopiere seinen Kommentar hier, weil es sehr relevant ist:

"Ich sehe nicht, dass der Knopf das Ereignis behandelt, dh ich habe keinen Klick -Handler auf der Schaltfläche, ich habe einen Klick -Handler (Mousedown) auf dem Stackpanel und daher würde ich denken, dass er an der Schaltfläche vorbei sprudeln würde Button handelt nicht und wird von der Stackpanel behandelt, was tut, oder? "

Sie haben Recht. Button handelt nicht mit dem MouseDown -Ereignis, da kein Handler bei dieser Kontrolle dafür angegeben wurde.

Aber dann ist MouseDown in irgendeiner Weise besonders. Zumindest in Windows -Formularen wird es verwendet, um Aktionen als Zeichnen und Ziehen zu initiieren. Wenn ein Steuerelement das Ereignis erhält, wird alle nachfolgenden Mausmeldungen fangen, auch wenn Sie keine Handler dafür definiert haben. Diese Falle erfolgt, wenn die Steuerung die Capture -Eigenschaft auf True setzt und dies effektiv verhindert, dass die nachfolgenden Ereignisse in die Luft sprudeln. Die Capture -Eigenschaft wird von Windows -Formularen auf False zurückgesetzt, wenn ein Mausup -Ereignis erhält.

Ich wiederhole, so funktioniert es in Windows-Formularen. Möglicherweise überprüfen Sie dies, aber es gibt keinen Grund, warum dies für WPF anders sein sollte.

Als Referenz: SE Der Abschnitt "Windows formuls Processing" at http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (Scrollen Sie leicht nach unten von der Mitte der Seite).

Hinweis: Siehe meinen Kommentar zu Arcturus Antwort als Referenz zu Blasen- und Tunnelereignissen erhöhen Sequenzen.

Tasteereignis unterdrückt die MouseDown und Mausup, da das Tastenereignis ein hohes Ereignis ist und ein Stück Code enthält, das den Flag -Handle true. Dies ist für MousDown unterdrückt, um dieses Problem zu beheben. Sie können diesen Code im Konstruktor des Fensters hinzufügen

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown),
    true);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top