XAML(Extensible Application Markup Language)は構造を入れ子で定義できます。
たとえば以下のような構造のXAMLがあったとします。
<Grid
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
x:Name="ParentGrid"
Tapped="ParentGrid_Tapped"
>
<Canvas
x:Name="Canvas2"
Tapped="Canvas2_Tapped"
>
<Button Width="200" Height="100"
x:Name="Button3"
Tapped="Button3_Tapped"
Content="Bubbleサンプル"
/>
</Canvas>
</Grid>
Gridコントロールの下にCanvasがあるというあまり意味の無い構造ですが、仕組みを理解するサンプルということでご勘弁を。
上記を実行すると以下のように左上にボタンが一つある画面が表示されます。
XAMLの入れ子構造はドキュメントアウトラインで確認できます。
イベントの中でも特殊なイベントRoutedEventがあります。
RoutedEventには以下の種類があります。
これらのイベントはバブリングという動作をします。
実際に動作を見てみましょう。上記XAMLのコードビハインドに以下のイベントが定義されています。
private void ParentGrid_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("ParentGrid_Tapped");
}
private void Canvas2_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("Canvas2_Tapped");
}
private void Button3_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("Button3_Tapped");
}
呼び出されるとイベントハンドラーは自分の名前をコンソールに出力します。
(イベントのクラスがTappedRoutedEventArgsとRoutedEventとなっていることにも注目してください)
このサンプルでボタンがクリックされた場合どのような出力が得られるか実行してみます。
Button3_Tapped
Canvas2_Tapped
ParentGrid_Tapped
この出力は上から順にイベントハンドラーを呼び出された並びです。
XAMLコントロールの入れ子でいうと最下層のボタンのタップイベントが発生した後、イベントは上位のキャンバス、さらに上のグリッドにイベントが伝播していることがわかります。
この動きは、RoutedEventの伝播を理解していないと予期しない動作をもたらすことになります。
イベントの伝播を行わないようにするにはコードビハインドを以下のように書き換えます。
private void ParentGrid_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("ParentGrid_Tapped");
}
private void Canvas2_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("Canvas2_Tapped");
e.Handled = true;
}
private void Button3_Tapped(object sender, TappedRoutedEventArgs e)
{
Debug.WriteLine("Button3_Tapped");
}
e.Handledをtrueに設定することでイベントの伝播は止まります。
プログラムを実行すると以下の出力が得られます。
Button3_Tapped
Canvas2_Tapped
イベントの伝播が止まりました。
Please give us your valuable comment