WPF - Événements routés

UNE routed eventest un type d'événement qui peut appeler des gestionnaires sur plusieurs écouteurs dans une arborescence d'éléments plutôt que simplement sur l'objet qui a déclenché l'événement. Il s'agit essentiellement d'un événement CLR pris en charge par une instance de la classe Routed Event. Il est enregistré auprès du système d'événements WPF. RoutedEvents a trois stratégies de routage principales qui sont les suivantes -

  • Événement direct
  • Événement bouillonnant
  • Événement de tunnel

Événement direct

Un événement direct est similaire aux événements dans les formulaires Windows qui sont déclenchés par l'élément à l'origine de l'événement.

Contrairement à un événement CLR standard, les événements acheminés directement prennent en charge la gestion des classes et ils peuvent être utilisés dans les paramètres d'événement et les déclencheurs d'événement dans votre style de contrôle personnalisé.

Un bon exemple d'un événement direct serait l'événement MouseEnter.

Événement bouillonnant

Un événement bouillonnant commence par l'élément d'où l'événement est originaire. Ensuite, il parcourt l'arborescence visuelle jusqu'à l'élément le plus élevé de l'arborescence visuelle. Ainsi, dans WPF, l'élément le plus élevé est probablement une fenêtre.

Événement de tunnel

Les gestionnaires d'événements sur la racine de l'arborescence des éléments sont appelés, puis l'événement se déplace dans l'arborescence visuelle vers tous les nœuds enfants jusqu'à ce qu'il atteigne l'élément dont l'événement est issu.

La différence entre un événement bouillonnant et un événement tunnel est qu'un événement tunnel commencera toujours par un aperçu.

Dans une application WPF, les événements sont souvent implémentés sous la forme d'une paire tunnel / bullage. Ainsi, vous aurez un aperçu MouseDown, puis un événement MouseDown.

Vous trouverez ci-dessous un exemple simple d'événement Routé dans lequel un bouton et trois blocs de texte sont créés avec certaines propriétés et événements.

<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>

Voici le code C # pour l'implémentation des événements Click pour Button, StackPanel et Window.

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"; 
      }
		
   } 
}

Lorsque vous compilez et exécutez le code ci-dessus, il produira la fenêtre suivante -

Lorsque vous cliquez sur le bouton, les blocs de texte seront mis à jour, comme indiqué ci-dessous.

Si vous souhaitez arrêter l'événement acheminé à un niveau particulier, vous devrez définir e.Handled = true;

Changeons le StackPanel_Click événement comme indiqué ci-dessous -

private void StackPanel_Click(object sender, RoutedEventArgs e) { 
   txt2.Text = "Click event is bubbled to Stack Panel"; 
   e.Handled = true; 
}

Lorsque vous cliquez sur le bouton, vous remarquerez que l'événement click ne sera pas dirigé vers la fenêtre et s'arrêtera au StackPanel et le 3 ème bloc de texte ne sera pas mis à jour.

Événements routés personnalisés

Dans le framework .NET, un événement routé personnalisé peut également être défini. Vous devez suivre les étapes ci-dessous pour définir un événement routé personnalisé en C #.

  • Déclarez et enregistrez votre événement acheminé avec l'appel système RegisterRoutedEvent.

  • Spécifiez la stratégie de routage, c'est-à-dire Bulle, Tunnel ou Direct.

  • Fournissez le gestionnaire d'événements.

Prenons un exemple pour en savoir plus sur les événements routés personnalisés. Suivez les étapes ci-dessous -

  • Créer un nouveau projet WPF avec WPFCustomRoutedEvent

  • Faites un clic droit sur votre solution et sélectionnez Ajouter> Nouvel élément ...

  • La boîte de dialogue suivante s'ouvre, sélectionnez maintenant Custom Control (WPF) et nommez-le MyCustomControl.

  • Clique le Add et vous verrez que deux nouveaux fichiers (Themes / Generic.xaml et MyCustomControl.cs) seront ajoutés dans votre solution.

Le code XAML suivant définit le style du contrôle personnalisé dans le fichier 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>

Ci-dessous, le code C # pour le MyCustomControl class qui hérite de la Control class dans lequel un événement routé personnalisé Click est créé pour le contrôle personnalisé.

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); 
      }
		
   } 
}

Voici l'implémentation d'événement routé personnalisé en C # qui affichera une boîte de message lorsque l'utilisateur cliquera dessus.

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"); 
      } 
		
   } 
}

Voici l'implémentation dans MainWindow.xaml pour ajouter le contrôle personnalisé avec un événement routé Click.

<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>

Lorsque le code ci-dessus est compilé et exécuté, il produira la fenêtre suivante qui contient un contrôle personnalisé.

Lorsque vous cliquez sur le contrôle personnalisé, il produira le message suivant.