WPF-ルーティングされたイベント
A routed eventは、イベントを発生させたオブジェクトだけでなく、要素ツリー内の複数のリスナーでハンドラーを呼び出すことができるタイプのイベントです。これは基本的に、RoutedEventクラスのインスタンスによってサポートされるCLRイベントです。WPFイベントシステムに登録されています。RoutedEventsには、次の3つの主要なルーティング戦略があります。
- 直接イベント
- バブリングイベント
- トンネルイベント
直接イベント
直接イベントは、イベントが発生した要素によって発生するWindowsフォームのイベントに似ています。
標準のCLRイベントとは異なり、直接ルーティングされたイベントはクラス処理をサポートし、カスタムコントロールのスタイル内のイベントセッターおよびイベントトリガーで使用できます。
直接イベントの良い例は、MouseEnterイベントです。
バブリングイベント
バブリングイベントは、イベントが発生した要素から始まります。次に、ビジュアルツリーを上ってビジュアルツリーの最上位の要素に移動します。したがって、WPFでは、最上位の要素はおそらくウィンドウです。
トンネルイベント
要素ツリールートのイベントハンドラーが呼び出され、イベントは、イベントが発生した要素に到達するまで、ビジュアルツリーを下ってすべての子ノードに移動します。
バブリングイベントとトンネリングイベントの違いは、トンネリングイベントは常にプレビューで開始されることです。
WPFアプリケーションでは、イベントはトンネリング/バブリングのペアとして実装されることがよくあります。したがって、MouseDownのプレビューとMouseDownイベントがあります。
以下に示すのは、いくつかのプロパティとイベントを使用してボタンと3つのテキストブロックが作成されるルーティングイベントの簡単な例です。
<Window x:Class = "WPFRoutedEvents.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click = "Window_Click" >
<Grid>
<StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click">
<StackPanel Margin = "10">
<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" />
</StackPanel>
<Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/>
</StackPanel>
</Grid>
</Window>
Button、StackPanel、およびWindowのClickイベント実装のC#コードを次に示します。
using System.Windows;
namespace WPFRoutedEvents {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
txt1.Text = "Button is Clicked";
}
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
}
private void Window_Click(object sender, RoutedEventArgs e) {
txt3.Text = "Click event is bubbled to Window";
}
}
}
上記のコードをコンパイルして実行すると、次のウィンドウが表示されます-
ボタンをクリックすると、以下に示すように、テキストブロックが更新されます。
ルーティングされたイベントを特定のレベルで停止する場合は、e.Handled = true;を設定する必要があります。
変更しましょう StackPanel_Click 以下に示すイベント-
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
e.Handled = true;
}
ボタンをクリックすると、クリックイベントがウィンドウにルーティングされず、スタックパネルで停止し、3番目のテキストブロックが更新されないことがわかります。
カスタムルーティングイベント
.NET Frameworkでは、カスタムルーティングイベントを定義することもできます。C#でカスタムルーティングイベントを定義するには、以下の手順に従う必要があります。
ルーティングされたイベントを宣言し、システムコールRegisterRoutedEventで登録します。
ルーティング戦略、つまりバブル、トンネル、またはダイレクトを指定します。
イベントハンドラーを提供します。
カスタムルーティングイベントの詳細を理解するために例を見てみましょう。以下の手順に従ってください-
WPFCustomRoutedEventを使用して新しいWPFプロジェクトを作成します
ソリューションを右クリックして、[追加]> [新しいアイテム...]を選択します。
次のダイアログが開きます。次に選択します。 Custom Control (WPF) 名前を付けます MyCustomControl。
クリック Add ボタンをクリックすると、2つの新しいファイル(Themes / Generic.xamlとMyCustomControl.cs)がソリューションに追加されることがわかります。
次のXAMLコードは、Generic.xamlファイルのカスタムコントロールのスタイルを設定します。
<ResourceDictionary
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCustomRoutedEvent">
<Style TargetType = "{x:Type local:MyCustomControl}">
<Setter Property = "Margin" Value = "50"/>
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate TargetType = "{x:Type local:MyCustomControl}">
<Border Background = "{TemplateBinding Background}"
BorderBrush = "{TemplateBinding BorderBrush}"
BorderThickness = "{TemplateBinding BorderThickness}">
<Button x:Name = "PART_Button" Content = "Click Me" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
以下に示すのは、のC#コードです。 MyCustomControl class から継承します Control class カスタムルーティングイベントClickがカスタムコントロール用に作成されます。
using System.Windows;
using System.Windows.Controls;
namespace WPFCustomRoutedEvent {
public class MyCustomControl : Control {
static MyCustomControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl),
new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
//demo purpose only, check for previous instances and remove the handler first
var button = GetTemplateChild("PART_Button") as Button;
if (button ! = null)
button.Click + = Button_Click;
}
void Button_Click(object sender, RoutedEventArgs e) {
RaiseClickEvent();
}
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(MyCustomControl));
public event RoutedEventHandler Click {
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
protected virtual void RaiseClickEvent() {
RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent);
RaiseEvent(args);
}
}
}
これは、ユーザーがクリックするとメッセージボックスを表示するC#でのカスタムルーティングイベントの実装です。
using System.Windows;
namespace WPFCustomRoutedEvent {
// <summary>
// Interaction logic for MainWindow.xaml
// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void MyCustomControl_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("It is the custom routed event of your custom control");
}
}
}
これは、ルーティングされたイベントClickを使用してカスタムコントロールを追加するためのMainWindow.xamlの実装です。
<Window x:Class = "WPFCustomRoutedEvent.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCustomRoutedEvent"
Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<local:MyCustomControl Click = "MyCustomControl_Click" />
</Grid>
</Window>
上記のコードをコンパイルして実行すると、カスタムコントロールを含む次のウィンドウが生成されます。
カスタムコントロールをクリックすると、次のメッセージが表示されます。