MSDN 기사가 말한 것처럼 버튼 버튼을 클릭하면 스태크 패널에 "버블 업 비주얼 트리"가없는 이유는 무엇입니까?

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

  •  20-08-2019
  •  | 
  •  

문제

MSDN 기사에서 WPF에서 라우팅 된 이벤트 및 명령 이해, 그것은 말한다

이벤트는 처리되거나 루트 요소에 도달 할 때까지 소스 요소에서 시각적 트리를 기포 (전파)합니다.

그러나이 예에서는 버튼을 클릭하면 부모의 스택 패널 이벤트가 처리하기 위해 "시각적 트리를 거품이 켜지지"않습니다., 즉 버튼을 클릭하면 이벤트가 없습니다.

왜 안 돼? 그때는 "버블 링"이라는 의미는 무엇을 의미합니까? 그렇지 않다면?

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로 바꿉니다.

미리보기를 사용하는 경우 스택 패널이 버튼이하기 전에 먼저 이벤트를 수신하는 것을 알 수 있습니다. 미리보기 이벤트는 터널 다운 접근법을 사용합니다.

다른 팁

다른 사람들이 말했듯이, 그것은 때문입니다 MouseDown 이벤트는 다음에 의해 처리됩니다 Button 더 거품이 생기기 전에. 반사기에서 이것을 볼 수 있습니다 ButtonBase.OnMouseLeftButtonDown:

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

한 가지 해결책은 다음을 듣는 것입니다 MouseDown 이벤트, 이벤트가 처리되었는지 신경 쓰지 않음을 나타냅니다. 당신은 이것을 할 수 있습니다 AddHandler 방법. 부울 오버로드가있어 이미 처리 된 이벤트를들을 수 있습니다.

XAML에서 Mousedown 핸들러를 설정하는 대신 어딘가 에서이 작업을 수행하면 :

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 자체를 클릭하면 버튼 클릭으로 특별히 듣기 때문에 어떤 이벤트가 발생하지 않습니다.

모든 메시지가 캡처되기 때문입니다 처리 버튼과 메시지가 중지됩니다 메시지가 중지됩니다 거기에 버블 링. 답은 질문의 텍스트에서 옳습니다.

이벤트는 소스 요소에서 시각적 트리 위로 거품 (전파)됩니다. 처리 될 때까지 또는 루트 요소에 도달합니다.

편집하다:

Edward Tanguay (OP)는이 답변에 대해 댓글을 달았으며 매우 관련성이 있기 때문에 그의 의견을 여기에 복사하고 있습니다.

"버튼이 이벤트를 처리하고있는 것을 보지 못합니다. 즉, 버튼에 클릭 핸들러가 없으므로 스택 패널에 클릭 핸들러 (Mousedown)가 있습니다. 버튼은 처리하지 않고 스택 패널로 처리됩니다. "

당신이 맞습니다. 버튼은 해당 컨트롤에서 핸들러가 지정되지 않았기 때문에 Mousedown 이벤트를 처리하지 않습니다.

그러나 Mousedown은 어떤 식 으로든 특별합니다. 최소한 Windows 형태에서는 컨트롤이 이벤트를 얻을 때 핸들러를 정의하지 않은 경우에도 모든 후속 마우스 메시지를 가두는 작업을 도면 및 드래그하는 역할을 시작하는 데 사용됩니다. 이 트랩은 컨트롤 세트가 속성을 true로 캡처 할 때 수행되며 이는 후속 이벤트가 거품이 발생하지 않도록 효과적으로 중단됩니다. 캡처 속성은 마우스 업 이벤트를 얻을 때 Windows 양식으로 False로 다시 설정됩니다.

반복합니다. 이것이 Windows 형태에서 작동하는 방식입니다. 이것을 두 번 확인하고 싶을 수도 있지만 IMHO WPF와 다른 이유는 없습니다.

참조 용 : SE "Windows Forms 처리"섹션은 http://blogs.msdn.com/jfoscoding/archive/2005/07/28/444647.aspx (페이지 중간에서 약간 아래로 스크롤).

참고 : 버블 및 터널링 이벤트에 대한 참조에 대한 Arcturu의 답변에 대한 내 의견을 참조하십시오.

버튼 이벤트는 버튼 이벤트 이벤트가 높기 때문에 Mousedown 및 Mouseup을 억제하고 플래그를 제공하는 코드 약간의 코드가 있어이 문제를 해결하기 위해 Mousdown을 억제 하여이 문제를 해결하기 위해이 코드를 추가 할 수 있습니다.

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown),
    true);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top