Comment créer un événement routé personnalisé (WPF .NET)

Les développeurs d’applications windows Presentation Foundation (WPF) et les auteurs de composants peuvent créer des événements routés personnalisés pour étendre les fonctionnalités des événements CLR (Common Language Runtime). Pour plus d’informations sur les fonctionnalités des événements routés, consultez Pourquoi utiliser des événements routés. Cet article décrit les principes fondamentaux de la création d’un événement routé personnalisé.

Prérequis

L’article suppose une connaissance de base des événements routés et que vous avez lu la vue d’ensemble des événements routés. Pour suivre les exemples de cet article, il vous aide à connaître le langage XAML (Extensible Application Markup Language) et savoir comment écrire des applications Windows Presentation Foundation (WPF).

Étapes des événements routés

Les étapes de base pour créer un événement routé sont les suivantes :

  1. Inscrivez une RoutedEvent méthode à l’aide de la RegisterRoutedEvent méthode.

  2. L’appel d’inscription retourne une RoutedEvent instance, appelée identificateur d’événement routé, qui contient le nom de l’événement inscrit, la stratégie de routage et d’autres détails d’événement. Affectez l’identificateur à un champ en lecture seule statique. Par convention :

    • L’identificateur d’un événement routé avec une stratégie de boublage est nommé <event name>Event. Par exemple, si le nom de l’événement est Tap alors l’identificateur doit être nommé TapEvent.
    • L’identificateur d’un événement routé avec une stratégie de tunneling est nommé Preview<event name>Event. Par exemple, si le nom de l’événement est Tap alors l’identificateur doit être nommé PreviewTapEvent.
  3. Définissez les accesseurs d’événements d’ajout et de suppression du CLR. Sans accesseurs d’événements CLR, vous ne pourrez ajouter ou supprimer des gestionnaires d’événements que par le biais d’appels directs aux méthodes et UIElement.RemoveHandler aux UIElement.AddHandler méthodes. Avec les accesseurs d’événements CLR, vous obtenez ces mécanismes d’affectation de gestionnaire d’événements :

    • Pour le langage XAML (Extensible Application Markup Language), vous pouvez utiliser la syntaxe d’attribut pour ajouter des gestionnaires d’événements.
    • Pour C#, vous pouvez utiliser les += opérateurs et -= les opérateurs pour ajouter ou supprimer des gestionnaires d’événements.
    • Pour VB, vous pouvez utiliser les instructions AddHandler et RemoveHandler pour ajouter ou supprimer des gestionnaires d’événements.
  4. Ajoutez une logique personnalisée pour déclencher votre événement routé. Par exemple, votre logique peut déclencher l’événement en fonction de l’état de l’entrée utilisateur et de l’application.

Exemple

L’exemple suivant implémente la CustomButton classe dans une bibliothèque de contrôles personnalisée. La CustomButton classe, qui dérive de Button:

  1. Inscrit un RoutedEvent nom ConditionalClick à l’aide de la RegisterRoutedEvent méthode et spécifie la stratégie de bouclage pendant l’inscription.
  2. Affecte l’instance RoutedEvent retournée à partir de l’appel d’inscription à un champ en lecture seule statique nommé ConditionalClickEvent.
  3. Définit les accesseurs d’événements d’ajout et de suppression du CLR.
  4. Ajoute une logique personnalisée pour déclencher l’événement routé personnalisé lorsque l’utilisateur CustomButton clique et qu’une condition externe s’applique. Bien que l’exemple de code déclenche l’événement ConditionalClick routé à partir de la méthode virtuelle substituée OnClick , vous pouvez déclencher votre événement comme vous le souhaitez.
public class CustomButton : Button
{
    // Register a custom routed event using the Bubble routing strategy.
    public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
        name: "ConditionalClick",
        routingStrategy: RoutingStrategy.Bubble,
        handlerType: typeof(RoutedEventHandler),
        ownerType: typeof(CustomButton));

    // Provide CLR accessors for assigning an event handler.
    public event RoutedEventHandler ConditionalClick
    {
        add { AddHandler(ConditionalClickEvent, value); }
        remove { RemoveHandler(ConditionalClickEvent, value); }
    }

    void RaiseCustomRoutedEvent()
    {
        // Create a RoutedEventArgs instance.
        RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);

        // Raise the event, which will bubble up through the element tree.
        RaiseEvent(routedEventArgs);
    }

    // For demo purposes, we use the Click event as a trigger.
    protected override void OnClick()
    {
        // Some condition combined with the Click event will trigger the ConditionalClick event.
        if (DateTime.Now > new DateTime())
            RaiseCustomRoutedEvent();

        // Call the base class OnClick() method so Click event subscribers are notified.
        base.OnClick();
    }
}
Public Class CustomButton
    Inherits Button

    ' Register a custom routed event with the Bubble routing strategy.
    Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
        name:="ConditionalClick",
        routingStrategy:=RoutingStrategy.Bubble,
        handlerType:=GetType(RoutedEventHandler),
        ownerType:=GetType(CustomButton))

    ' Provide CLR accessors to support event handler assignment.
    Public Custom Event ConditionalClick As RoutedEventHandler

        AddHandler(value As RoutedEventHandler)
            [AddHandler](ConditionalClickEvent, value)
        End AddHandler

        RemoveHandler(value As RoutedEventHandler)
            [RemoveHandler](ConditionalClickEvent, value)
        End RemoveHandler

        RaiseEvent(sender As Object, e As RoutedEventArgs)
            [RaiseEvent](e)
        End RaiseEvent

    End Event

    Private Sub RaiseCustomRoutedEvent()

        ' Create a RoutedEventArgs instance.
        Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)

        ' Raise the event, which will bubble up through the element tree.
        [RaiseEvent](routedEventArgs)

    End Sub

    ' For demo purposes, we use the Click event as a trigger.
    Protected Overrides Sub OnClick()

        ' Some condition combined with the Click event will trigger the ConditionalClick event.
        If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()

        ' Call the base class OnClick() method so Click event subscribers are notified.
        MyBase.OnClick()

    End Sub
End Class

L’exemple inclut une application WPF distincte qui utilise le balisage XAML pour ajouter une instance de l’instance CustomButton à un StackPanel, et affecter la Handler_ConditionalClick méthode en tant que ConditionalClick gestionnaire d’événements pour les éléments et StackPanel1 les CustomButton éléments.

<Window x:Class="CodeSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
        Title="How to create a custom routed event" Height="100" Width="300">

    <StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
        <custom:CustomButton
            Name="customButton"
            ConditionalClick="Handler_ConditionalClick"
            Content="Click to trigger a custom routed event"
            Background="LightGray">
        </custom:CustomButton>
    </StackPanel>
</Window>

Dans code-behind, l’application WPF définit la méthode du Handler_ConditionalClick gestionnaire d’événements. Les méthodes de gestionnaire d’événements ne peuvent être implémentées que dans code-behind.

// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
    string senderName = ((FrameworkElement)sender).Name;
    string sourceName = ((FrameworkElement)e.Source).Name;

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the ConditionalClick routed event raised on {sourceName}.");
}

// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
//     triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
//     triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)

    Dim sourceName As String = CType(e.Source, FrameworkElement).Name
    Dim senderName As String = CType(sender, FrameworkElement).Name

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the ConditionalClick routed event raised on {sourceName}.")

End Sub

' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
'     triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
'     triggered by the ConditionalClick routed event raised on CustomButton.

Quand CustomButton un clic est fait :

  1. L’événement ConditionalClick routé est déclenché le CustomButton.
  2. Le Handler_ConditionalClick gestionnaire d’événements auquel il est attaché CustomButton est déclenché.
  3. L’événement ConditionalClick routé traverse l’arborescence d’éléments vers StackPanel1.
  4. Le Handler_ConditionalClick gestionnaire d’événements auquel il est attaché StackPanel1 est déclenché.
  5. L’événement ConditionalClick routé poursuit l’arborescence d’éléments pouvant déclencher d’autres gestionnaires d’événements ConditionalClick attachés à d’autres éléments parcourus.

Le Handler_ConditionalClick gestionnaire d’événements obtient les informations suivantes sur l’événement qui l’a déclenché :

  • Objet expéditeur , qui est l’élément auquel le gestionnaire d’événements est attaché. CustomButton La sender première fois que le gestionnaire s’exécute et StackPanel1 la deuxième fois.
  • Objet RoutedEventArgs.Source , qui est l’élément qui a déclenché l’événement à l’origine. Dans cet exemple, la valeur Source est toujours CustomButton.

Remarque

Une différence clé entre un événement routé et un événement CLR est qu’un événement routé traverse l’arborescence d’éléments, recherchant des gestionnaires, tandis qu’un événement CLR ne traverse pas l’arborescence d’éléments et les gestionnaires ne peuvent joindre qu’à l’objet source qui a déclenché l’événement. Par conséquent, un événement sender routé peut être n’importe quel élément parcouru dans l’arborescence d’éléments.

Vous pouvez créer un événement de tunneling de la même façon qu’un événement de bubbling, sauf que vous allez définir la stratégie de routage dans l’appel Tunneld’inscription d’événement sur . Pour plus d’informations sur les événements de tunneling, consultez les événements d’entrée WPF.

Voir aussi