2013-09-04 7 views
10

나는 버블 링과 터널링이 어떻게 작동하는지 이해합니다. 그러나, 나는 그들을 사용하는 것에 대해 혼란스러워. 이유 :WPF에서 터널링 및 버블 링 이벤트는 언제 유용합니까?

마우스 클릭 이벤트를 처리하고 싶습니다. 버블 링하려면 MouseDown이 있으며 터널을 연결하려면 PreviewMouseDown이 있어야합니다. 그러나 MouseDown이 반드시 사용자가 컨트롤을 클릭했음을 의미하지는 않습니다. 사용자가 버튼을 눌렀을 때 이탈하여 클릭을 취소 할 수 있습니다. 버튼을 클릭하지 않으면 아무 것도 변경하고 싶지 않습니다.

제 질문은 Bubbling/Tunneling 전략이 어떻게 유용할까요?

답변

8

이벤트가 RoutedEventArgs으로 나열되면 이벤트가 라우트됩니다. 라우트 된 이벤트는 Bubble, Tunnel 또는 Direct의 RoutingStrategy를 지원합니다.

private void Grid_Click(object sender, RoutedEventArgs e) 
{ 
    MessageBox.Show("Button Test clicked!"); 
} 

RoutedEventArgs이 지정, 그래서 라우트 된 이벤트 것 :의이 Button.Click의 이벤트 핸들러에서 살펴 보자. 미리보기은 이름에 지정되지 않았으므로이 Bubble 이벤트입니다. 당신이 TestButton 클릭하면

<Grid ButtonBase.Click="Grid_Click"> 
    <Button Name="TestButton" Width="100" Height="30" Content="Test" /> 
</Grid> 

, 이벤트가 Grid 이상으로 상승하는 것입니다, 그리고 메시지가 표시됩니다 : 이것은 다음과 같은 방법으로 입증 할 수

버튼 테스트 클릭을! 표준 컨트롤의 많은 Tunneling

Usefulness of Bubbling/Tunneling strategies

는 이벤트를 수신 예를 들어 등 KeyDown, MouseDown 등 - DataGrid 제어 할 수 있습니다. Enter 키를 눌러 레코드 추가라는 기능을 원합니다. 그러나 DataGrid에는 이미 KeyDown 이벤트가있어 이벤트가 발생하지 않습니다. 따라서 터널 이벤트에서 로직을 수행해야합니다 (PreviewKeyDown). KeyDown 이벤트 이전에 작동합니다. RichTextBoxControl에도 동일하게 적용됩니다. Bubbling

때때로, 당신은 특정 이벤트에 대한 전역 핸들러가 필요합니다, 그래서 VisualTree의 모든 컨트롤했다. 자연스럽게, 당신은 그것을 할 수없는 직접적인 사건입니다. 따라서 무대에서는 버블 링 이벤트가 발생합니다.

또 다른 이유는 WPF의 이데올로기입니다. Image, 다른 Button 등 :

enter image description here

사용자는 ButtonTextBlock/Image을 클릭하면이 Button 아무것도 포함 할 수 있습니다. 클릭이 Button에 있음을 어떻게 알 수 있습니까? Bubbling 이벤트의 도움으로 맞습니다.

자세한 내용은 다음을 참조하십시오

,691 다음 Button에 클릭의

private void Grid_Click(object sender, RoutedEventArgs e) 
{ 
    String message = "#" + eventCounter.ToString() + ":\r\n" + 
      " Sender: " + sender.ToString() + ":\r\n" + 
      " Source: " + e.Source + ":\r\n" + 
      " Original Source: " + e.OriginalSource; 

    lstEvents.Items.Add(message); 
} 

결과 : 나는 Click 핸들러를 조금 변경

Understanding Routed Events and Commands In WPF

Edit

enter image description here

+0

그러나 내가 아는 한, 클릭은 버블 링 이벤트가 아닌 직접 이벤트입니다. – SanSolo

+1

@SanSolo : 직접 보낸 경우 'Button Test Clicked!'메시지가 나타나지 않습니다. 'Button'이 아닌'Grid'에 대한 핸들러를 설정하고'Button'을 클릭하면 그 이벤트는'Grid'에 대해 작동합니다. 'Button' 이벤트가 올라와'Grid'에 왔습니다. 내가 아는 한 직접 클릭 이벤트는 *'WinForms' *에있었습니다. –

+1

@SanSolo : 내 편집을 참조하십시오. –

1

당신이 말했듯이 버블 링/터널링의 개념을 알고 있으므로 그렇게하지 않을 것입니다. 그러나 이것은 이러한 이벤트가 의도 한 것입니다. 즉, Mouse 버튼이 컨트롤 또는 해당 children.Unit에 있는지 알려주는 것입니다. 이벤트가 제대로 작동하고 있습니다. 시나리오의 경우 Click 버튼 이벤트를 사용해야합니다. 마우스가 버튼 자체에 위아래로있었습니다.

감사

+0

클릭은 직접적인 이벤트입니다. 내 혼란은 버블 링/터널링 이벤트의 사용에 관한 것입니다. – SanSolo

3

안녕하세요 당신은 좋은 기사 그물에이 regading하지만 여전히 나는이 대답을하려고합니다 얻을 수 있지만.

버튼에 단일 직사각형으로 구성된 매우 단순한 모양을 지정하고 간단한 텍스트를 내용으로 제공한다고 가정합니다. 기본 비주얼이 있더라도 텍스트와 직사각형의 두 가지 요소가 있습니다. 마우스가 텍스트 또는 사각형 위에 있는지 여부에 관계없이 단추는 마우스 클릭에 응답해야합니다. 표준 .NET 이벤트 처리 모델에서는 두 요소 모두에 MouseLeftButtonUp 이벤트 처리기를 등록해야합니다. WPF의 내용 모델을 활용하면

이 문제는 더 악화 될 것이다. 버튼은 캡션으로 일반 텍스트가있는 것에 국한되지 않으며 콘텐츠로 개체를 포함 할 수 있습니다. 아래 xaml은 특별히 야심적 인 것은 아니지만 심지어 에는 여섯 가지 가시 요소가 있습니다. 노란색 윤곽선 원, 눈 두 점, 입에 대한 곡선, 텍스트 및 버튼 배경 자체. 모든 요소에 대해 이벤트를 연결하면 지루하고 비효율적입니다. MouseDown 작업이 코드 비트에는 8 개의 MouseDownEvents를 추가해야합니다.

<Button PreviewMouseDown="PreviewMouseDownButton" MouseDown="MouseDownButton"> 
     <Grid PreviewMouseDown="PreviewMouseDownGrid" MouseDown="MouseDownGrid"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <Canvas PreviewMouseDown="PreviewMouseDownCanvas" MouseDown="MouseDownCanvas" Width="20" Height="18" VerticalAlignment="Center"> 
       <Ellipse PreviewMouseDown="PreviewMouseDownEllipse" MouseDown="MouseDownEllipse" x:Name="myEllipse" Canvas.Left="1" Canvas.Top="1" Width="16" Height="16" Fill="Yellow" Stroke="Black" /> 
       <Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" /> 
       <Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" MouseDown="MouseDownEllipse" Height="3" Fill="Black" /> 
       <Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" MouseDown="Path_MouseDown_1"/> 
      </Canvas> 
      <TextBlock Grid.Column="1" MouseDown="TextBlock_MouseDown_1">Click!</TextBlock> 
     </Grid> 
    </Button> 

WPF 오히려 일반 사건보다 더 철저버블/터널/일반 RoutedEvents을 사용합니다. 대신에 이벤트를 발생시킨 요소에 연결된 핸들러를 호출하면 WPF는 트리의 사용자 인터페이스 요소를 걷고 노드에 연결된 모든 라우트의 핸들러를 원래 요소에서 사용자 인터페이스의 루트까지 호출합니다 나무.

+0

그 대답은 내 질문의 제목 인 버블 링/터널링의 필요성을 분명히합니다.그러나 나는 그것이 Click과 같은 결정적인 액션이 아니라고 가정 할 때 MouseUp 또는 MouseDown을 사용하는 이유에 대해 여전히 혼란 스럽습니다. MousewheelUp/Down 나는 그것이 유용한 시나리오를 볼 수 있습니다. 그러나 MouseUp의 경우, 우리는 뭔가 바뀌고, 사용자는 버튼에서 멀어지고, 클릭은 없습니다 ... 어디에서 사용합니까? – SanSolo