Почему кнопка не нажимает на событие «Bubble Up Visual Tree» в StackPanel, как говорится в статье MSDN?

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

  •  20-08-2019
  •  | 
  •  

Вопрос

В статье MSDN Понимание направленных событий и команд в WPF, Здесь утверждается

Событие пузырит (распространяется) вверх по визуальному дереву из исходного элемента, пока оно не будет обработано, либо не достигнет корневого элемента.

Однако в этом примере, когда вы нажимаете кнопку, Это не «пузырьть визуальное дерево», чтобы получить обработку родительского события StackPanel, IE нажав на кнопку, не запускает событие.

Почему бы и нет? Что они значат тогда под "пузырьком" если не это?

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>

код-бледность:

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

    }
}
Это было полезно?

Решение

Событие пузырится, пока оно не будет обработан ...

Поскольку кнопка что -то делает с нажатиями мыши, она поглощает вашу мышь событие и превращает его в Clickevent.

Если вы используете PreviewMouseDown, вы видите, что StackPanel впервые получает событие до того, как кнопка сделает.

Другие советы

Как говорили другие, это потому, что MouseDown событие обрабатывается Button Прежде чем его можно будет пузыриться дальше. Вы можете увидеть это в отражателе, в ButtonBase.OnMouseLeftButtonDown:

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

Одним из решений является прослушивание MouseDown событие и укажите, что вам все равно, если это событие будет обработано. Вы можете сделать это с AddHandler метод У него есть логическая перегрузка, которая позволяет выслушать события, которые уже обрабатываются.

Если вы сделаете это где -то вместо того, чтобы установить обработчик MouseDown в XAML:

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

Вы получите все MouseDown События на TheStackPanel, независимо от того, были ли с ними обработаны.

Кроме того, если вы хотите, чтобы StackPanel получила событие, измените StackPanel XAML на:

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

и подпись события на:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e)

В этом случае StackPanel получит событие нажатия кнопки. Тем не менее, нажатие на саму StackPanel не запускает какое -либо событие, так как она конкретно слушает кнопку нажатия.

Это потому, что все сообщения захватываются обрабатывается кнопкой и сообщениями останавливаются Сообщение останавливается Там пузырится. Ответ прямо в тексте вашего вопроса:

Событие пузырит (распространяется) вверх по визуальному дереву из исходного элемента Пока это не будет обработано или он достигает корневого элемента.

РЕДАКТИРОВАТЬ:

Эдвард Тангуэй (OP) прокомментировал этот ответ, и я копирую его комментарий здесь, потому что он очень актуален:

«Я не вижу, что кнопка обрабатывает событие, то есть у меня нет обработчика нажатия на кнопке, у меня есть обработчик щелчка (Mousedown) на StackPanel, и, следовательно, я думаю, что она будет пузыриться мимо кнопки с момента кнопки Кнопка не обрабатывает его и не обрабатывает StackPanel, что делает, верно? "

Ты прав. Кнопка не обрабатывает событие Mousedown, потому что для этого контроля не было указано ни одного обработчика HA.

Но тогда Муседаун в некотором роде. По крайней мере, в формах Windows он используется для инициирования действий в качестве рисования и перетаскивания, поэтому, когда элемент управления получает событие, оно продолжает улавливать все последующие сообщения мыши, даже если вы не определили для него обработчиков. Эта ловушка выполняется, когда управление устанавливает свойство захвата на True, и это эффективно останавливает пузырьки последующих событий. Свойство захвата возвращается к False Forms Forms, когда он получает событие MouseUp.

Я повторяю, именно так это работает в формах Windows, вы можете дважды проверить это, но IMHO нет причин, по которым это должно быть иначе для WPF.

Для справки: SE Раздел «Обработка форм Windows» на http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (Слегка прокрутите от середины страницы).

ПРИМЕЧАНИЕ. См. Мой комментарий на ответ Арктуру для ссылки на события пузырьков и туннелирования. Повышение последовательностей.

Кнопка события подавляют Mousedown и MouseUp, потому что событие кнопки - это событие на высоком уровне, и у него есть кусочек кода, который дает ручку флага True Причина, подавленная для Mousdown для решения этой проблемы, вы можете добавить этот код в конструктор окна

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown),
    true);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top