Подтвердить что ты не робот

Почему в StackPanel не указывается событие нажатия кнопки "bubble up visual tree" в статье MSDN?

В статье MSDN Общие сведения о маршрутизированных событиях и командах В WPF указано

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

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

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

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

    }
}
4b9b3361

Ответ 1

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

Так как Button делает что-то с помощью щелчков мыши, он поглощает событие мыши и превращает его в ClickEvent.

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

Ответ 2

Как говорили другие, это потому, что событие MouseDown обрабатывается Button до того, как его можно продолжить. Вы можете видеть это в Reflector, в 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, независимо от того, были ли они обработаны.

Ответ 3

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

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

и сигнатуру события:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e)

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

Ответ 4

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

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

EDIT:

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

"Я не вижу, чтобы кнопка обрабатывала событие, т.е. у меня нет обработчика кликов на кнопке. У меня есть обработчик кликов (MouseDown) на StackPanel, и, следовательно, я думаю, что это будет пузыриться., так как кнопка не обрабатывает его и обрабатывается стековой панелью, которая делает это?"

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

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

Повторяю, так он работает в Windows Forms, вам может потребоваться дважды проверить это, но IMHO нет причин, почему это должно быть иначе для WPF.

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

Примечание. См. мой комментарий к ответу Арктуру для справки о событиях с появлением пузырьков и туннелей.

Ответ 5

событие кнопки Подавляет мышь и мышь, потому что событие кнопки является событием высокого уровня и имеет бит кода, который дает флаг handle true this cause. Подавлено для mousdown для решения этой проблемы. Вы можете добавить этот код в конструктор окна

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