2009-03-19 10 views
20

Nell'articolo MSDN Understanding Routed Events and Commands In WPF, essa affermaPerché il pulsante non fa clic sull'evento "bolla su albero visivo" su StackPanel come afferma l'articolo MSDN?

un evento bolla (propagazione) l'albero visuale dall'elemento sorgente fino a quando è stato trattato o raggiunge l'elemento radice.

Tuttavia, in questo esempio, quando si fa clic sul pulsante, non "bolla l'albero visuale" per ottenere gestito dal genitore StackPanel evento, cioè cliccando sugli incendi pulsante nessun caso.

Perché no? Cosa significano allora "borbottando" se non questo?

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

    } 
} 

risposta

22

L'evento bolle su, fino a quando non viene gestito ...

Poiché il tasto fa qualcosa con il tuo mouse fa clic, assorbe l'evento del mouse e lo trasforma in ClickEvent.

Se si utilizza il PreviewMouseDown, si vede che lo StackPanel riceve prima l'evento prima che il pulsante fa .. eventi Anteprima utilizzare il tunnel down ..

+1

cosa fa il pulsante con il mio clic del mouse? Non ho alcun attributo click nell'elemento, non sto gestendo l'evento click nel codice sottostante, quindi come possiamo dire che il pulsante sta facendo qualcosa con i clic del mouse? –

+0

PreviewMouseDown ha funzionato, grazie. –

+2

Vero, ma l'implementazione predefinita del pulsante è di assorbire l'evento del mouse per trasformarlo in un evento click ... anche se non fai nulla con il clic ... – Arcturus

1

è perché tutti i messaggi vengono catturati maneggiato con il pulsante e i messaggi fermano il messaggio si interrompe che bolle lì. La risposta è proprio nel testo di vostra domanda:

Un evento bolla (propagarsi) l'albero visuale dall'elemento fonte fino a quando è stato gestito o raggiunge l'elemento principale.

EDIT:

Edward Tanguay (OP) ha commentato questa risposta e sto copiando il suo commento qui perché è molto rilevante:

"non vedo che il pulsante IS gestendo l'evento, cioè non ho un gestore di clic sul pulsante, ho un gestore di clic (MouseDown) sullo StackPanel e quindi penserei che sarebbe in bolla su PASSATO il pulsante poiché il pulsante non lo gestisce e viene gestito da lo stackpanel che fa, giusto? "

Hai ragione. Button non sta gestendo l'evento MouseDown perché non è stato specificato alcun gestore per quel controllo.

Ma, quindi, MouseDown è particolare in qualche modo. Almeno in Windows Form viene utilizzato per avviare azioni come disegnare e trascinare, quindi, quando un controllo riceve l'evento, procede a intercettare tutti i successivi messaggi del mouse anche se non sono stati definiti gestori per esso.Questa trappola viene eseguita quando il controllo imposta la proprietà Capture su True e in tal modo si impedisce effettivamente che gli eventi successivi vengano fatti gorgogliare. La proprietà Capture viene impostata su False da Windows Form quando viene rilevato un evento MouseUp.

Ripeto, questo è il modo in cui funziona in Windows Form, si consiglia di ricontrollare questo, ma, IMHO non c'è motivo per cui questo dovrebbe essere diverso per WPF.

Per riferimento: vedere la sezione "Elaborazione di Windows Form" allo http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (scorrere leggermente verso il basso dal centro della pagina).

Nota: vedere il mio commento alla risposta di Arcturu per un riferimento su eventi di bolla e tunneling che generano sequenze.

+0

Non vedo che il pulsante STI gestisca l'evento, ad es.Non ho un gestore di clic sul pulsante, ho un gestore di clic (MouseDown) sullo StackPanel e quindi penserei che rispolvera il pulsante PAST dal momento che il pulsante non lo gestisce e viene gestito dallo stackpanel che lo fa, destra? –

+0

Hai ragione. Ho modificato la mia risposta. – vmarquez

7

Inoltre, se si desidera che lo StackPanel per ricevere l'evento, cambiare il codice XAML StackPanel a:

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

e la firma dell'evento:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e) 

In questo caso, lo StackPanel sarà ricevere l'evento click del pulsante. Tuttavia, facendo clic sullo stackpanel non si attiva alcun evento, in quanto esso ascolta in modo specifico un clic del pulsante.

+0

hmm, ho visto anche Button.Click negli articoli ma il mio StackPanel non ha quell'attributo (?), L'unico attributo simile che ottengo in intellisense è "ButtonBase.Click" che mi dà "Nessun sovraccarico per" TheStackPanel_MouseDown 'corrisponde a delegato' System.Windows.RoutedEventHandler '", perché? –

+0

Hmmm, funziona per me sia con ButtonBase.Click che con Button.Click in XAML (credo che Button.Click non venga visualizzato in intellisense - ma dovrebbe funzionare) - e con la firma dell'evento specificata. Hai modificato MouseButtonEventArgs in RoutedEventArgs? – Razzie

8

Come altri hanno già detto, è perché l'evento MouseDown viene gestito dallo Button prima che possa essere ulteriormente gorgogliato. Si può vedere questo in Reflector, in ButtonBase.OnMouseLeftButtonDown:

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

Una soluzione è quella di ascoltare per un evento MouseDown, e indicare che non si cura se l'evento viene gestito. Puoi farlo con il metodo AddHandler. Ha un sovraccarico booleano che ti consente di ascoltare eventi già gestiti.

Se si fa questo da qualche parte invece di impostare il gestore MouseDown in XAML:

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

Riceverai tutti MouseDown eventi su TheStackPanel, indipendentemente dal fatto che sono stati trattati.

+0

cos'è "MouseDownEvent"? RoutedEvent è una classe sigillata, quindi alcuni oggetti devono contenere istanze di quelli? – flq

+0

Ah, ho trovato qualcosa. 'Mouse.AddXXX (DependencyObject, EventHandler);' – flq

2

evento tasto Sopprime il MouseDown e MouseUp perché eventi pulsante è l'evento di alto livello e hanno porzione di codice che danno bandiera gestire vera questa causa Soppresso per mousdown per risolvere questo problema è possibile aggiungere questo codice nel costruttore della finestra di

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown), 
    true); 
Problemi correlati