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>

上記のコードをコンパイルして実行すると、カスタムコントロールを含む次のウィンドウが生成されます。

カスタムコントロールをクリックすると、次のメッセージが表示されます。