ルーティングイベントとは
- 観点を機能に置いた場合、イベントを生成したオブジェクト上だけでなく、要素ツリー内の複数のリスナー上でハンドラーを呼び出すことができる種類のイベント
- 観点を実装に置いた場合、ルーティング イベントは、RoutedEvent クラスのインスタンスによってサポートされる CLR イベントであり、Windows Presentation Foundation (WPF) イベント システムによって処理される
サンプル例
Buttonが3つあり、親要素にStatckPanelがあり、さらに、親要素にBorderがあり、さらに親要素にWindowがある画面。
Buttonのどれかを押すと、StackPanelのClickイベントハンドラが呼ばれ、次に、BorderのClickイベントハンドラが呼ばれ、次に、WindowsのClickイベントハンドラが呼ばれる。
[MainWindow.xaml]
<Window x:Class="WpfApp1.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" mc:Ignorable="d" Title="MainWindow" SizeToContent="WidthAndHeight" Button.Click="WindowClickHandler"> <Grid> <Border Height="50" Width="Auto" BorderBrush="Gray" BorderThickness="1" Button.Click="BorderClickHandler"> <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="StackPanelClickHandler"> <Button Name="YesButton" Width="Auto" >Yes</Button> <Button Name="NoButton" Width="Auto" >No</Button> <Button Name="CancelButton" Width="Auto" >Cancel</Button> </StackPanel> </Border> </Grid> </Window>
[MainWindow.xaml.cs]
using System.Windows; namespace WpfApp1 { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void StackPanelClickHandler(object sender, RoutedEventArgs e) { FrameworkElement feSource = e.Source as FrameworkElement; switch (feSource.Name) { case "YesButton": MessageBox.Show("[StackPanel] Push Yes Button!"); break; case "NoButton": MessageBox.Show("[StackPanel] Push No Button!"); break; case "CancelButton": MessageBox.Show("[StackPanel] Push Cancel Button!"); break; } // e.Handledをtrueにしないかぎり、親要素にボタンクリックイベントに伝搬していく e.Handled = false; } private void BorderClickHandler(object sender, RoutedEventArgs e) { FrameworkElement feSource = e.Source as FrameworkElement; switch (feSource.Name) { case "YesButton": MessageBox.Show("[Border] Push Yes Button!"); break; case "NoButton": MessageBox.Show("[Border]Push No Button!"); break; case "CancelButton": MessageBox.Show("[Border]Push Cancel Button!"); break; } // e.Handledをtrueにしないかぎり、親要素にボタンクリックイベントに伝搬していく e.Handled = false; } private void WindowClickHandler(object sender, RoutedEventArgs e) { FrameworkElement feSource = e.Source as FrameworkElement; switch (feSource.Name) { case "YesButton": MessageBox.Show("[Window] Push Yes Button!"); break; case "NoButton": MessageBox.Show("[Window]Push No Button!"); break; case "CancelButton": MessageBox.Show("[Window]Push Cancel Button!"); break; } e.Handled = true; } } }
ハンドラの引数であるRoutedEventArgsに定義されているHandledプロパティを使用すると、イベントルーティングを制御できます。
ハンドラ内でHandledプロパティをtrueにセットした場合、それ以降のイベントルーティングは呼び出されません。
例えば、StackPanelClickHandler
メソッドのe.Handled = false
をe.Handled = true
に変更すると、イベントが親要素(Border
)に伝搬しなくなります。
RoutedEventについては、この後、記載します。
参考ページ
- ルーティング イベントの概要
https://msdn.microsoft.com/ja-jp/library/ms742806(v=vs.100).aspx