ルーティング・イベントとは
WPFのイベントは、ルーティング・イベントです。WPFでは、要素やコントロールは、入れ子にできます。今回の例で使用するプログラムでは、Windowの中に、StackPanelがあり、その中に、Buttonがあります。この入れ子関係にある要素やコントロールで、発生したイベントは、連鎖し、この入れ子関係にある要素やコントロールでイベントが発生します。
レイアウトコンテナのイベントで、レイアウトコンテナ上のボタンで発生したイベントを取得する
StackPanel要素にイベントを追加します。StackPanel要素は、Clickイベントを持っていません。そこで、PreviewMouseLeftButtonDownイベントとPreviewMouseLeftButtonUpイベントを追加し、マウスの左ボタンが押されたとき、テキストブロックに、マウスの左ボタンが押されたことを示すテキストを表示し、マウスの左ボタンが離されれたとき、テキストを消すコードを記述します。
<Window x:Class="_2ButtonEvents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="140" Width="300">
<StackPanel>
<TextBlock Name="tb" FontSize="14">テキストブロック</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" PreviewMouseLeftButtonDown="StackPanel_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="StackPanel_PreviewMouseLeftButtonUp">
<Button Height="50" Width="100" Margin="15" FontSize="14">ボタン A</Button>
<Button Height="50" Width="100" Margin="15" FontSize="14">ボタン B</Button>
</StackPanel>
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Input;
namespace _2ButtonEvents
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
tb.Text = "マウスの左ボタンが押されました";
}
private void StackPanel_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
tb.Text = null;
}
}
}
ボタン要素にイベントがなくても、ボタンが配置されているレイアウトコンテナにイベントを設定する事で、ボタン要素上で発生するイベントを取得できることが確認できました。
PreviewMouseLeftButtonDownイベントとPreviewMouseLeftButtonUpイベントを追加したのは、StackPanel要素ですが、ボタンを押すとイベントが発生していることが確認できました。
レイアウト上のボタンのどれでイベントが発生しているかを判断する
先程紹介したコードで、レイアウトコンテナ上に配置したイベントで、レイアウトコンテナ上のボタンで発生したイベントを取得できることが確認できました。
どのボタンが押されたか、区別出来ると、使いみちが増えます。
どちらのボタンが押されているか識別できるようにコードのStackPanel_PreviewMouseLeftButtonDownを以下のように変更します。
private void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
string buttonCaption;
buttonCaption = e.Source.ToString();
tb.Text = buttonCaption;
}
このコードでは、イベントが発生したボタンによって、「System.WindowsControls.Button: ボタンA」のように、「コントールの名前:Contentプロパティの内容」として、表示されます。
イベントが発生したボタンのContent属性の値を取得する。
先程のコードでは、イベントの発生したボタンが、「コントールの名前:Contentプロパティの内容」として、表示されました。しかし、この形式で出力されると使いにくいので、 Contentプロパティの内容だけが表示されるようにコードを以下のように変更します。
using System.Windows.Controls;
private void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Button srcButton = e.Source as Button;
tb.Text = srcButton.Content.ToString();
}
このコードでは、Contentプロパティの内容だけが表示されます。
まとめ
このように、ルーティング・イベントを使用すると、電卓アプリケーションのような、複数のボタンを持つアプリケーションで、イベントの記述を削減できます。
最終的なコードを示します。
<Window x:Class="_2ButtonEvents.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="140" Width="300">
<StackPanel>
<TextBlock Name="tb" FontSize="14">テキストブロック</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" PreviewMouseLeftButtonDown="StackPanel_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="StackPanel_PreviewMouseLeftButtonUp">
<Button Height="50" Width="100" Margin="15" FontSize="14">ボタン A</Button>
<Button Height="50" Width="100" Margin="15" FontSize="14">ボタン B</Button>
</StackPanel>
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace _2ButtonEvents
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void StackPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Button srcButton = e.Source as Button;
tb.Text = srcButton.Content.ToString();
}
private void StackPanel_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
tb.Text = null;
}
}
}