2009-03-19 12 views
20

W artykule MSDN Understanding Routed Events and Commands In WPF, stwierdzaDlaczego zdarzenie click button button nie powoduje "upuszczania drzewa wizualnego" do StackPanel jako stan artykułu MSDN?

wydarzeniem będzie bańka (propagacji) w górę drzewa wizualnej z elementu źródłowego dopóki nie został on obsługiwany lub osiągnie element główny.

Jednak w tym przykładzie, po kliknięciu przycisku to nie „bubble up wizualne drzewo”, aby obsługiwane przez rodzica StackPanel imprezy, to znaczy kliknięciu na przycisk pożarów żadnego zdarzenia.

Dlaczego nie? Co oznaczają one przez "bulgotanie" jeśli nie to?

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> 

kod z opóźnieniem:

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."; 
     } 

    } 
} 

Odpowiedz

22

Impreza propaguje się, dopóki nie zostanie obsługiwane ...

Ponieważ przycisk robi coś z kliknięcia myszą pochłaniają zdarzenia myszy i zamieniają je w ClickEvent.

Jeśli używasz PreviewMouseDown, widać, że StackPanel najpierw odbiera zdarzenie przed przycisk robi .. Podgląd zdarzeń stosowanie metody tunelowania w dół ..

+1

Co robi przycisk z moim kliknięciem myszy? Nie mam atrybutu kliknięcia w elemencie, nie obsługuję zdarzenia kliknięcia w kodzie, więc jak możemy powiedzieć, że przycisk wykonuje coś za pomocą kliknięć myszy? –

+0

PreviewMouseDown zadziałało, dziękuję. –

+2

To prawda, ale domyślna implementacja przycisku polega na zaabsorbowaniu zdarzenia myszy, aby przekształcić je w zdarzenie kliknięcia ... nawet jeśli nic nie zrobisz kliknięciem ... – Arcturus

1

to dlatego, że wszystkie wiadomości są przechwytywane obsługiwane za pomocą przycisku i wiadomości zatrzymaj się wiadomość zatrzymuje się bulgotanie tam. Odpowiedź jest w tekście dane pytanie:

Zdarzenie będzie bańka (propagacji) w górę drzewa wizualnej z elementu źródłowego dopóki nie został on obsługiwany lub osiągnie element główny.

EDIT:

Edward Tanguay (PO) skomentował tej odpowiedzi i jestem kopiując jego komentarz tutaj, bo to jest bardzo istotne:

„Nie widzę, że przycisk jest obsługa zdarzenia, tj. nie mam obsługi kliknięcia na przycisku, mam uchwyt do klikania (MouseDown) na StackPanel, a więc myślę, że będzie to bańki PAST przycisk, ponieważ przycisk nie obsługuje go i dostać obsługiwane przez sterpanel, który działa, prawda?

Masz rację. Przycisk nie obsługuje zdarzenia MouseDown, ponieważ dla tego formantu nie określono dla niego obsługi.

Ale, MouseDown jest w pewien sposób szczególny. Przynajmniej w Windows Forms jest on używany do inicjowania akcji jako rysowania i przeciągania, więc gdy formant dostaje zdarzenie, przechwytuje wszystkie kolejne komunikaty myszy, nawet jeśli nie zdefiniowałeś dla niego procedur obsługi.Ta pułapka jest wykonywana, gdy kontrolka ustawia właściwość Przechwytuj na wartość Prawda, co skutecznie powstrzymuje kolejne zdarzenia przed bąblowaniem. Właściwość przechwytywania jest przywracana do wartości False przez Windows Forms, gdy otrzyma zdarzenie MouseUp.

Powtarzam, to jest sposób, w jaki działa w Windows Forms, możesz to sprawdzić dwukrotnie, ale IMHO nie ma powodu, dla którego to powinno być inne dla WPF.

Dla odniesienia: Zobacz sekcję "Przetwarzanie formularzy Windows" pod numerem http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (przewiń nieco w dół ze środka strony).

Uwaga: Zobacz mój komentarz do odpowiedzi Arcturu na odniesienie do sekwencji podskakujących bąbelków i tuneli.

+0

Nie widzę, aby przycisk obsługiwał zdarzenie, tj.Nie mam obsługi kliknięcia na przycisku, mam obsługę obsługi kliknięcia (MouseDown) na StackPanelu, a więc myślę, że będzie to bańka PAST przycisk, ponieważ przycisk nie obsługuje go i dostać się do obsługi przez Stackpanel, który robi, dobrze? –

+0

Masz rację. Edytowałem swoją odpowiedź. – vmarquez

7

Ponadto, jeśli chcesz stackpanel otrzymywać zdarzenia, zmienić XAML stackpanel do:

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

oraz podpis zdarzeń do:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e) 

W tym przypadku, StackPanel będzie odbieranie zdarzenia kliknięcia przycisku. Jednak kliknięcie samego panelu sterującego nie wywoła żadnego zdarzenia, ponieważ nasłuchuje ono kliknięcia przycisku.

+0

hmm, widziałem również Button.Click w artykułach, ale mój StackPanel nie ma tego atrybutu (?), Jedyny podobny atrybut jaki dostaję w intellisense to "ButtonBase.Click", który daje mi "Brak przeciążenia" TheStackPanel_MouseDown "pasuje do delegata" System.Windows.RoutedEventHandler "", dlaczego tak jest? –

+0

Hmmm, działa dla mnie zarówno z ButtonBase.Click i Button.Click w XAML (Wierzę, że Button.Click po prostu nie wyświetla się w intellisense - ale powinno działać) - oraz z podanym sygnaturą zdarzenia. Czy zmieniłeś MouseButtonEventArgs na RoutedEventArgs? – Razzie

8

Jak powiedzieli inni, dzieje się tak dlatego, że wydarzenie MouseDown zostaje obsłużone przez Button, zanim będzie można je dalej barbotować. Można to zobaczyć w reflektor, w ButtonBase.OnMouseLeftButtonDown:

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

Jednym z rozwiązań jest nasłuchiwać zdarzenia MouseDown i wskazują, że nie obchodzi mnie, czy zdarzenie jest obsługiwane. Możesz to zrobić za pomocą metody AddHandler. Ma przeciążenie boolowskie, które pozwala wykrywać zdarzenia, które są już obsługiwane.

Jeśli zrobisz to gdzieś zamiast ustawiania obsługi MouseDown w XAML:

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

otrzymasz wszystkie MouseDown wydarzenia na TheStackPanel, niezależnie od tego, czy zostały one obsługiwane.

+0

co to jest "MouseDownEvent"? RoutedEvent jest klasą zamkniętą, więc niektóre obiekty muszą nosić takie obiekty? – flq

+0

Ach, znalazłem coś. 'Mouse.AddXXX (DependencyObject, EventHandler);' – flq

2

przycisk wydarzenie Wyłącza mousedown i mouseUp ponieważ zdarzenie przycisk jest wydarzenie wysoki poziom i mieć kawałek kodu, który daje flag obsługiwać prawda to przyczyna tłumione mousdown aby rozwiązać ten problem, można dodać ten kod w konstruktorze okna

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown), 
    true); 
Powiązane problemy