Pourquoi le bouton cliquez-vous sur l'événement «Bubble Up Visual Tree» à StackPanel comme l'indique l'article MSDN?

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

  •  20-08-2019
  •  | 
  •  

Question

Dans l'article MSDN Comprendre les événements et les commandes acheminés dans WPF, il est dit

Un événement bouillonnera (propager) l'arborescence visuelle de l'élément source jusqu'à ce qu'il ait été géré ou atteigne l'élément racine.

Cependant, dans cet exemple, lorsque vous cliquez sur le bouton, Il ne "bouillonne pas l'arbre visuel" pour se faire gérer par l'événement Parent StackPanel, c'est-à-dire en cliquant sur le bouton ne tire aucun événement.

Pourquoi pas? Que signifient-ils alors par "bouillonner" Sinon?

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

    }
}
Était-ce utile?

La solution

L'événement bouillonne jusqu'à ce qu'il soit manipulé ...

Étant donné que le bouton fait quelque chose avec votre clic de souris, il absorbe votre événement de souris et le transforme en clickevent.

Si vous utilisez le préviewmousdown, vous voyez que le StackPanel reçoit d'abord l'événement avant le bouton.

Autres conseils

Comme d'autres l'ont dit, c'est parce que le MouseDown L'événement est géré par le Button avant qu'il ne puisse être bouillonnant. Vous pouvez voir cela dans Reflector, dans ButtonBase.OnMouseLeftButtonDown:

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

Une solution consiste à écouter un MouseDown Événement, et indiquez que vous ne vous souciez pas si l'événement est géré. Vous pouvez le faire avec le AddHandler méthode. Il a une surcharge booléenne qui vous permet d'écouter des événements qui sont déjà gérés.

Si vous faites cela quelque part au lieu de définir le gestionnaire de musiques dans XAML:

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

Vous recevrez tout MouseDown événements TheStackPanel, peu importe s'ils ont été manipulés.

De plus, si vous souhaitez que le StackPanel reçoive l'événement, modifiez le pilepanel xaml pour:

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

et la signature de l'événement à:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e)

Dans ce cas, le StackPanel recevra l'événement de clic du bouton. Cependant, cliquer sur le StackPanel lui-même ne tirera aucun événement, car il écoute spécifiquement un clic de bouton.

C'est parce que tous les messages sont capturés manipulé par bouton et les messages s'arrêtent Le message s'arrête bouillonner là-bas. La réponse est juste dans le texte de votre question:

Un événement bouillonnera (propager) l'arborescence visuelle de l'élément source jusqu'à ce qu'il ait été traité ou il atteint l'élément racine.

ÉDITER:

Edward Tanguay (OP) a commenté cette réponse et je copie son commentaire ici parce qu'il est très pertinent:

"Je ne vois pas que le bouton gère l'événement, c'est-à-dire que je n'ai pas de gestionnaire de clic sur le bouton, j'ai un gestionnaire de clics (MousDown) sur le StackPanel et donc je pense qu'il bouillonnerait devant le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton depuis le bouton Le bouton ne le gére pas et ne se fait pas gérer par le StackPanel, ce qui fait, non? "

Vous avez raison. Le bouton ne gère pas l'événement Mousedown car aucun gestionnaire n'a été spécifié pour cela à ce contrôle.

Mais, alors, Mousedown est particulière d'une manière ou d'une autre. Au moins dans les formulaires Windows, il est utilisé pour initier des actions comme dessin et glisser, lorsqu'un contrôle obtient l'événement, il continue de piéger tous les messages de souris suivants même si vous n'avez pas défini les gestionnaires. Ce piège est effectué lorsque le contrôle définit la propriété de capture sur true et cela empêche efficacement les événements ultérieurs d'être bouillonnés. La propriété de capture est recueillie sur False par les formulaires Windows lorsqu'il obtient un événement de souris.

Je répète, c'est ainsi que cela fonctionne sous les formes Windows, vous voudrez peut-être vérifier cela, mais, à mon humble avis, il n'y a aucune raison pour que cela soit différent pour WPF.

Pour référence: Se la section "Traitement des formulaires Windows" http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (Faites défiler légèrement le milieu de la page).

Remarque: Voir mon commentaire sur la réponse d'Arcturu pour une référence sur les événements de bulles et les événements de tunneling augmentent les séquences.

Événement de bouton Supprimer le MousDown et MouseUp car l'événement Button est un événement de haut niveau et avoir un peu de code qui donne à l'indicateur la poignée vraie cette cause supprimée pour que Mousdown résolve ce problème, vous pouvez ajouter ce code dans le constructeur de la fenêtre

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown),
    true);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top