1. RoutedEvent란?
WPF에서 사용될 때, 이벤트를 발생 시킨 개체(예를 들면 버튼)에서만 아니라 버튼과 관계된 상위 요소를 호출할 수 있는 이벤트 형식입니다.
일반적으로 이벤트 경로는 이벤트를 발생 시킨 개체부터 루트에 도달할 때까지 상위 요소로 "Bubbling"됩니다. 반대의 개념을 "Tunneling"이라고 합니다.
위의 사진에서 루트 요소로 향하는 점선(위 방향)은 Bubbling이며, 리프 요소로 향하는 점선(아래 방향)은 Tunneling입니다.
2. Bubbling
Bubbling과 Tunneling을 설명하기 위한 WPF 프로그램으로 설명하겠습니다.
* Bubbling Example 화면은 Window - StackPanel - Button 순서로 xaml에 작성되어 있습니다.
* Tunneling Example 화면은 StackPanel - Button 순서로 xaml에 작성되어 있습니다. (Window에는 설정하지 않음)
1) 버블링 버튼을 클릭 시, 리프 요소(Button)부터 호출이 됨을 확인할 수 있습니다.
3. Tunneling
1) 터널링은 버블링과 반대로, 버튼을 클릭할 시 루트 요소(StackPanel)부터 호출됨을 확인할 수 있습니다.
Bubbling 영역
Tunneling 영역
<Window x:Class="RoutedEvent.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:RoutedEvent"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"ButtonBase.Click="Window_Click"Background="Beige"><Grid Margin="10"><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition Height="30"/></Grid.RowDefinitions><StackPanel ButtonBase.Click = "StackPanel_Click"><TextBlock FontSize = "18" Margin = "5" Text = "Bubbling Example" HorizontalAlignment="Center" FontWeight="Bold"/><TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1" /><TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2" /><TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3" /><Button Content = "Click me(in Panel)" Click = "Button_Click" Width = "150"/><!--Button -> StackPanel -> Window --></StackPanel><StackPanel Grid.Row="1" PreviewMouseDown="StackPanel_PreviewMouseDown" Background="LightGreen"><TextBlock FontSize = "18" Margin = "5" Text = "Tunneling Example" HorizontalAlignment="Center" FontWeight="Bold"/><TextBlock Name = "txt4" FontSize = "18" Margin = "5" Text = "This is a TextBlock 4" /><TextBlock Name = "txt5" FontSize = "18" Margin = "5" Text = "This is a TextBlock 5" /><Button Content = "Click me(in Panel)" Width = "150" PreviewMouseDown="Button_PreviewMouseDown" Background="LightBlue"/></StackPanel><Button Grid.Row="2" Height="20" Width = "150" Content = "Bubble(not in Panel)" Click = "Button_Click" HorizontalAlignment="Left"/><Button Grid.Row="2" Height="20" Width = "150" Content = "Tunnel(not in Panel)" PreviewMouseDown="Button_PreviewMouseDown" HorizontalAlignment="Right"/></Grid></Window>
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace RoutedEvent{/// <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";MessageBox.Show("Window(Bubbling)");}private void StackPanel_Click(object sender, RoutedEventArgs e){txt2.Text = "Click event is bubbled to Stack Panel";MessageBox.Show("Stack Panel(Bubbling)");//이 단계에서 라우트 이벤트를 정지함(윈도우 이벤트로 넘어가지 않음)//e.Handled = true;}private void Button_Click(object sender, RoutedEventArgs e){txt1.Text = "Button is Clicked";MessageBox.Show("Button(Bubbling)");}private void StackPanel_PreviewMouseDown(object sender, MouseButtonEventArgs e){txt5.Text = "Click event is tunneled to Stack Panel";MessageBox.Show("Stack Panel(Tunneling)");}private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e){txt4.Text = "Button is Clicked";MessageBox.Show("Button(Tunneling)");}}}