9장. WPF 이벤트 라우팅(RoutedEvent), 버블링/ 터널링/다이렉트 이벤트
- C#/WPF
- 2021. 5. 8. 18:08
9장. WPF 이벤트 라우팅(RoutedEvent), 버블링/ 터널링/다이렉트 이벤트
참조
목적
- WPF 이벤트 라우팅(RoutedEvent), 버블링/터널링/다이렉트 이벤트에 대해서 학습합니다.
정의
- 이벤트 라우팅은 어떤 이벤트가 컨트롤의 하위 또는 상위로 전달되는 것 을 이야기하며 WPF에서 광범위하게 이용되는 방법입니다.
- 이벤트 라우팅은 세가지로 분류할 수 있는데 이벤트가 발생했을 때 현재 컨트롤에서 상위로 올라가면서 전달되는 경우를 "버블링 이벤트(Bubbleing Event)" 라고 하고 반대로 자식 컨트롤로 전달되는 경우를 "터널링(Tunneling Event)" 라고 합니다. 하나의 엘리먼트에서만 발생하게 된다면 다이렉트 이벤트(Direct Event) 라고 합니다.
- 터널링 이벤트 의 경우 접두사로 preview를 붙이는데, PreviewMouseDown, PreviewDragDown 등으로 쓰여지는 것들을 Tunneling 이벤트라고 이해하면 됩니다.
- 터널링이벤트 는 최상위 부모 컨트롤로부터 자기자신까지 이벤트가 진행되는 것인데, 이벤트가 자식 요소에게 전달되기 전에 부모의 이벤트가 먼저 호출되므로 부모 이벤트가 먼저 호출할 수 있는 기회를 제공하며, 자식의 이벤트 발생을 막거나 자식 이벤트 처리 전에 부모 요소가 무엇인가 수행할 필요가 있는 경우에 유용합니다.
- 이벤트 핸들러 메서드는 RoutedEventArgs 매개변수를 가지는데 Source 속성을 통해 실제 이벤트를 발생시킨 요소에 대한 참조를 제공하며, 이 속성은 여러 요소에서 발생한 이벤트를 동일한 방법으로 처리하고자 할 때 특히 유용합니다.
- WPF의 라우팅된 이벤트에서 object sender는 이벤트를 등록한 객체, RoutedEventArgs의 Source 속성은 실제 이벤트를 발생시킨 객체를 의미합니다.
- WPF의 이벤트 라우팅 모델은 자동으로 이벤트를 상위 객체로 라우팅 시켜줍니다. (버블링 이벤트)
Bubbleing(자식에서 부모로 위로 올라감) 실습
MainWindow.xaml
<Window x:Class="WPF09_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF09_Test"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="350"
ButtonBase.Click="Window_Click">
<Grid>
<StackPanel Margin="20" ButtonBase.Click="StackPanel_Click">
<StackPanel Margin="10">
<TextBlock x:Name="txt1" FontSize="18"
Margin="5"
Text="This is a TextBlock1"/>
<TextBlock x:Name="txt2" FontSize="18"
Margin="5"
Text="This is a TextBlock2"/>
<TextBlock x:Name="txt3" FontSize="18"
Margin="5"
Text="This is a TextBlock3"/>
</StackPanel>
<Button Margin="10" Content="Click me"
Click="Button_Click"
Width="80"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WPF09_Test
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Click(object sender, RoutedEventArgs e)
{
txt3.Text = "Click event is bubbled to Window";
}
private void StackPanel_Click(object sender, RoutedEventArgs e)
{
txt2.Text = "Click event is bubbled to Stack Panel";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
txt1.Text = "Button is Clicked";
}
}
}
실행 결과
- 상위 객체로 라우팅 되는 것을 막으려면 RoutedEventArgs의 Handled 속성을 true로 설정하면 된다.
- 버튼 클릭 이벤트에 "e.Handled = true" 라고 하면 버튼까지만, 스택 패널 클릭 이벤트에 "e.Handled = true" 라고 한다면 스택 패널 까지만 이벤트가 전달됩니다.
MainWindow.xaml.cs
using System.Windows;
namespace WPF09_Test
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Click(object sender, RoutedEventArgs e)
{
txt3.Text = "Click event is bubbled to Window";
}
private void StackPanel_Click(object sender, RoutedEventArgs e)
{
txt2.Text = "Click event is bubbled to Stack Panel";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
txt1.Text = "Button is Clicked";
e.Handled = true; //상위로 Routing 되는 걸 막으려면 e.Handled = true 설정하면 된다.
}
}
}
실행 결과
- Preview 이벤트에 Handled 속성을 지정하면 Preview 이벤트의 터널링이 중단될 뿐만 아니라 버블링 이벤트의 발생도 중단 됩니다.
Tunneling(부모에서 자식으로) 실습
MainWindow.xaml
<Window x:Class="WPF09_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF09_Test"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="350"
PreviewMouseDown="Window_PreviewMouseDown">
<StackPanel Height="120" HorizontalAlignment="Center"
VerticalAlignment="Center" Width="200"
Background="Transparent"
PreviewMouseDown ="StackPanel_PreviewMouseDown">
<Border Margin="20" Padding="5" Background="LightYellow"
BorderBrush="SteelBlue" BorderThickness="3 5 3 5"
CornerRadius="3"
VerticalAlignment="Top">
<Button Margin="20" Height="50" Width="50"
PreviewMouseDown="Button_PreviewMouseDown"/>
</Border>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WPF09_Test
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
string mouseActivity = string.Empty;
public MainWindow()
{
InitializeComponent();
}
private void Window_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
mouseActivity = "PreviewMouseDown Window\n";
MessageBox.Show(mouseActivity);
}
private void StackPanel_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
mouseActivity = "PreviewMouseDown StackPanel \n";
MessageBox.Show(mouseActivity);
}
private void Button_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
mouseActivity = "PreviewMouseDown Button \n";
MessageBox.Show(mouseActivity);
}
}
}
실행 결과
728x90
'C# > WPF' 카테고리의 다른 글
11장. WPF 데이터바인딩 실습 (0) | 2021.05.08 |
---|---|
10장. WPF 데이터바인딩(DataBinding)이란? (0) | 2021.05.08 |
8장. WPF 의존프로퍼티(DependencyProperty) 란? (0) | 2021.05.08 |
7장. WPF ListBox와 LINQ쿼리를 이용한 간단한 데이터바인딩 (0) | 2021.05.08 |
6장. WPF Data Trigger 란? (0) | 2021.05.08 |
이 글을 공유하기