Vue d’ensemble des événements routés (WPF .NET)

Les développeurs d’applications windows Presentation Foundation (WPF) et les auteurs de composants peuvent utiliser des événements routés pour propager des événements via une arborescence d’éléments et appeler des gestionnaires d’événements sur plusieurs écouteurs de l’arborescence. Ces fonctionnalités ne sont pas trouvées dans les événements CLR (Common Language Runtime). Plusieurs événements WPF sont des événements routés, tels que ButtonBase.Click. Cet article décrit les concepts d’événements routés de base et fournit des conseils sur le moment et la façon de répondre aux événements routés.

Important

La documentation du Guide du bureau pour .NET 7 et .NET 6 est en cours de construction.

Prérequis

Cet article suppose une connaissance de base du Common Language Runtime (CLR), de la programmation orientée objet et de la façon dont la disposition des éléments WPF peut être conceptualisée en tant qu’arborescence. 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 WPF.

Qu’est-ce qu’un événement routé ?

Vous pouvez envisager des événements routés du point de vue fonctionnel ou de l’implémentation :

  • D’un point de vue fonctionnel , un événement routé est un type d’événement qui peut appeler des gestionnaires sur plusieurs écouteurs dans une arborescence d’éléments, pas seulement sur la source d’événement. Un écouteur d’événements est l’élément où un gestionnaire d’événements est attaché et appelé. Une source d’événement est l’élément ou l’objet qui a déclenché à l’origine un événement.

  • Du point de vue de l’implémentation , un événement routé est un événement inscrit auprès du système d’événements WPF, soutenu par une instance de la RoutedEvent classe et traité par le système d’événements WPF. En règle générale, un événement routé est implémenté avec un événement CLR « wrapper » pour activer l’attachement de gestionnaires en XAML et en code-behind comme vous le feriez pour un événement CLR.

Les applications WPF contiennent généralement de nombreux éléments, qui ont été déclarés en XAML ou instanciés dans le code. Les éléments d’une application existent dans son arborescence d’éléments. Selon la façon dont un événement routé est défini, lorsque l’événement est déclenché sur un élément source, il :

  • Fait défiler l’arborescence d’éléments de l’élément source vers l’élément racine, qui est généralement une page ou une fenêtre.
  • Tunnels vers le bas dans l’arborescence d’éléments de l’élément racine vers l’élément source.
  • Ne traverse pas l’arborescence d’éléments et se produit uniquement sur l’élément source.

Considérez l’arborescence d’éléments partiels suivante :

<Border Height="30" Width="200" BorderBrush="Gray" BorderThickness="1">
    <StackPanel Background="LightBlue" Orientation="Horizontal" Button.Click="YesNoCancelButton_Click">
        <Button Name="YesButton">Yes</Button>
        <Button Name="NoButton">No</Button>
        <Button Name="CancelButton">Cancel</Button>
    </StackPanel>
</Border>

L’arborescence d’éléments s’affiche comme indiqué :

Yes, No, and Cancel buttons.

Chacun des trois boutons est une source d’événement potentielle Click . Lorsque l’un des boutons est cliqué, il déclenche l’événement Click qui se déclenche du bouton à l’élément racine. Les Button éléments et Border les gestionnaires d’événements n’ont pas de gestionnaires d’événements attachés, mais le StackPanel fait. Peut-être d’autres éléments plus haut dans l’arborescence qui ne sont pas affichés ont Click également des gestionnaires d’événements attachés. Lorsque l’événement Click atteint l’élément StackPanel , le système d’événements WPF appelle le YesNoCancelButton_Click gestionnaire qui lui est attaché. L’itinéraire d’événement de l’événement Click dans l’exemple est : Button ->StackPanel ->Border éléments> parents successifs.

Remarque

L’élément qui a déclenché à l’origine un événement routé est identifié comme étant le RoutedEventArgs.Source paramètre du gestionnaire d’événements. L’écouteur d’événements est l’élément où le gestionnaire d’événements est attaché et appelé, et est identifié comme expéditeur dans les paramètres du gestionnaire d’événements.

Scénarios de niveau supérieur pour les événements routés

Voici quelques-uns des scénarios qui ont motivé le concept d’événement routé et le distinguent d’un événement CLR classique :

  • Composition et encapsulation des contrôles : différents contrôles dans WPF ont un con mode tente l riche. Par exemple, vous pouvez placer une image à l’intérieur d’une Buttonimage qui étend efficacement l’arborescence visuelle du bouton. Toutefois, l’image ajoutée ne doit pas briser le comportement de test d’accès du bouton, qui doit répondre lorsqu’un utilisateur clique sur les pixels de l’image.

  • Points de pièce jointe du gestionnaire singulier : vous pouvez inscrire un gestionnaire pour l’événement de Click chaque bouton, mais avec des événements routés, vous pouvez attacher un seul gestionnaire, comme illustré dans l’exemple XAML précédent. Cela vous permet de modifier l’arborescence d’éléments sous le gestionnaire singulier, comme l’ajout ou la suppression de boutons supplémentaires, sans avoir à inscrire l’événement de Click chaque bouton. Lorsque l’événement est déclenché, la Click logique du gestionnaire peut déterminer à partir de laquelle l’événement provient. Le gestionnaire suivant, spécifié dans l’arborescence d’éléments XAML précédemment illustré, contient cette logique :

    private void YesNoCancelButton_Click(object sender, RoutedEventArgs e)
    {
        FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement;
        switch (sourceFrameworkElement.Name)
        {
            case "YesButton":
                // YesButton logic.
                break;
            case "NoButton":
                // NoButton logic.
                break;
            case "CancelButton":
                // CancelButton logic.
                break;
        }
        e.Handled = true;
    }
    
    Private Sub YesNoCancelButton_Click(sender As Object, e As RoutedEventArgs)
        Dim frameworkElementSource As FrameworkElement = TryCast(e.Source, FrameworkElement)
    
        Select Case frameworkElementSource.Name
            Case "YesButton"
                ' YesButton logic.
            Case "NoButton"
                ' NoButton logic.
            Case "CancelButton"
                ' CancelButton logic.
        End Select
    
        e.Handled = True
    End Sub
    
  • Gestion des classes : les événements routés prennent en charge un gestionnaire d’événements de classe que vous définissez dans une classe. Les gestionnaires de classes gèrent un événement avant tout gestionnaire d’instance pour le même événement sur une instance de la classe.

  • Référencement d’un événement sans réflexion : chaque événement routé crée un RoutedEvent identificateur de champ pour fournir une technique d’identification d’événement robuste qui ne nécessite pas de réflexion statique ou d’exécution pour identifier l’événement.

Implémentation des événements routés

Un événement routé est un événement inscrit auprès du système d’événements WPF, soutenu par une instance de la RoutedEvent classe et traité par le système d’événements WPF. L’instance RoutedEvent , obtenue à partir de l’inscription, est généralement stockée en tant que public static readonly membre de la classe qui l’a inscrite. Cette classe est appelée classe « propriétaire » d’événement. En règle générale, un événement routé implémente un événement CLR identiquement nommé « wrapper ». Le wrapper d’événements CLR contient add et remove accesseurs pour permettre l’attachement de gestionnaires en XAML et en code-behind via la syntaxe d’événement spécifique au langage. remove Les add accesseurs remplacent leur implémentation CLR et appellent l’événement AddHandler et RemoveHandler les méthodes routés. Le mécanisme de stockage et de connexion des événements routés est conceptuellement similaire à la façon dont une propriété de dépendance est une propriété CLR sauvegardée par la DependencyProperty classe et inscrite auprès du système de propriétés WPF.

L’exemple suivant enregistre l’événement Tap routé, stocke l’instance retournée RoutedEvent et implémente un wrapper d’événements CLR.

// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    name: "Tap",
    routingStrategy: RoutingStrategy.Bubble,
    handlerType: typeof(RoutedEventHandler),
    ownerType: typeof(CustomButton));

// Provide CLR accessors for adding and removing an event handler.
public event RoutedEventHandler Tap
{
    add { AddHandler(TapEvent, value); }
    remove { RemoveHandler(TapEvent, value); }
}
' Register a custom routed event using the Bubble routing strategy.
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
    name:="Tap",
    routingStrategy:=RoutingStrategy.Bubble,
    handlerType:=GetType(RoutedEventHandler),
    ownerType:=GetType(CustomButton))

' Provide CLR accessors for adding and removing an event handler.
Public Custom Event Tap As RoutedEventHandler
    AddHandler(value As RoutedEventHandler)
        [AddHandler](TapEvent, value)
    End AddHandler

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

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

Stratégies de routage

Les événements routés utilisent l’une des trois stratégies de routage suivantes :

  • Bubbling : Initialement, les gestionnaires d’événements sur la source d’événement sont appelés. L’événement routé est ensuite acheminé vers des éléments parents successifs, appelant à son tour leurs gestionnaires d’événements, jusqu’à ce qu’il atteigne la racine de l’arborescence d’éléments. La plupart des événements routés utilisent la stratégie de routage par propagation. Les événements routés de boublage sont généralement utilisés pour signaler les modifications d’entrée ou d’état des contrôles composites ou d’autres éléments d’interface utilisateur.

  • Tunneling : Au début, les gestionnaires d’événements situés à la racine de l’arborescence d’éléments sont appelés. L’événement routé est ensuite acheminé vers des éléments enfants successifs, appelant à son tour leurs gestionnaires d’événements, jusqu’à ce qu’il atteigne la source d’événement. Les événements qui suivent un itinéraire de tunneling sont également appelés événements en préversion . Les événements d’entrée WPF sont généralement implémentés en tant que paires d’aperçu et de bulle.

  • Direct : seuls les gestionnaires d’événements sur la source d’événement sont appelés. Cette stratégie de non-routage est analogue aux événements d’infrastructure de l’interface utilisateur Windows Forms, qui sont des événements CLR standard. Contrairement aux événements CLR, les événements routés directs prennent en charge la gestion des classes et peuvent être utilisés par EventSetters et EventTriggers.

Pourquoi utiliser des événements routés ?

En tant que développeur d’applications, vous n’avez pas toujours besoin de savoir ou de vous soucier que l’événement que vous gérez est implémenté en tant qu’événement routé. Les événements routés ont un comportement spécial, mais ce comportement est largement invisible si vous gérez un événement sur l’élément qui l’a déclenché. Toutefois, les événements routés sont pertinents lorsque vous souhaitez attacher un gestionnaire d’événements à un élément parent afin de gérer les événements déclenchés par des éléments enfants, tels que dans un contrôle composite.

Les écouteurs d’événements routés n’ont pas besoin des événements routés qu’ils gèrent pour être membres de leur classe. Tout UIElement ou ContentElement peut être un écouteur d’événements pour n’importe quel événement routé. Étant donné que les éléments visuels dérivent ou UIElementContentElementque vous pouvez utiliser des événements routés comme une « interface » conceptuelle qui prend en charge l’échange d’informations d’événement entre des éléments disparates dans une application. Le concept d'« interface » pour les événements routés s’applique particulièrement aux événements d’entrée.

Les événements routés prennent en charge l’échange d’informations d’événement entre les éléments le long de l’itinéraire d’événement, car chaque écouteur a accès à la même instance de données d’événement. Si un élément modifie quelque chose dans les données d’événement, cette modification est visible par les éléments suivants dans l’itinéraire d’événement.

Outre l’aspect du routage, vous pouvez choisir d’implémenter un événement routé au lieu d’un événement CLR standard pour ces raisons :

  • Certaines fonctionnalités de style et de création de modèles WPF, telles que EventSetters et EventTriggers, nécessitent que l’événement référencé soit un événement routé.

  • Les événements routés prennent en charge les gestionnaires d’événements de classe qui gèrent un événement devant tous les gestionnaires d’instances pour le même événement sur n’importe quelle instance de la classe d’écouteur. Cette fonctionnalité est utile dans la conception du contrôle, car votre gestionnaire de classes peut appliquer des comportements de classe pilotés par les événements qui ne peuvent pas être supprimés accidentellement par un gestionnaire d’instances.

Attacher et implémenter un gestionnaire d’événements routés

En XAML, vous attachez un gestionnaire d’événements à un élément en déclarant le nom de l’événement en tant qu’attribut sur l’élément d’écouteur d’événement. La valeur de l’attribut est le nom de votre méthode de gestionnaire. La méthode de gestionnaire doit être implémentée dans la classe partielle code-behind de la page XAML. L’écouteur d’événements est l’élément où le gestionnaire d’événements est attaché et appelé.

Pour un événement membre (hérité ou autre) de la classe d’écouteur, vous pouvez attacher un gestionnaire comme suit :

<Button Name="Button1" Click="Button_Click">Click me</Button>

Si l’événement n’est pas membre de la classe de l’écouteur, vous devez utiliser le nom d’événement qualifié sous la forme .<owner type>.<event name> Par exemple, étant donné que la StackPanel classe n’implémente pas l’événement Click , pour attacher un gestionnaire à un StackPanelClick événement qui se déclenche jusqu’à cet élément, vous devez utiliser la syntaxe du nom d’événement qualifié :

<StackPanel Name="StackPanel1" Button.Click="Button_Click">
    <Button>Click me</Button>
</StackPanel>

La signature de la méthode de gestionnaire d’événements dans code-behind doit correspondre au type délégué de l’événement routé. Le sender paramètre du RoutedEventHandler délégué de l’événement Click spécifie l’élément auquel le gestionnaire d’événements est attaché. Le args paramètre du RoutedEventHandler délégué contient les données d’événement. Une implémentation de code-behind compatible pour le Button_Click gestionnaire d’événements peut être :

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Click event logic.
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Click event logic.
End Sub

Bien qu’il RoutedEventHandler s’agit du délégué de gestionnaire d’événements routés de base, certains contrôles ou scénarios d’implémentation nécessitent différents délégués qui prennent en charge des données d’événements plus spécialisées. Par exemple, pour l’événement DragEnter routé, votre gestionnaire doit implémenter le DragEventHandler délégué. Ainsi, votre code de gestionnaire peut accéder à la DragEventArgs.Data propriété dans les données d’événement, qui contient la charge utile du Presse-papiers à partir de l’opération de glisser.

La syntaxe XAML pour l’ajout de gestionnaires d’événements routés est la même que pour les gestionnaires d’événements CLR standard. Pour plus d’informations sur l’ajout de gestionnaires d’événements en XAML, consultez XAML dans WPF. Pour obtenir un exemple complet de l’attachement d’un gestionnaire d’événements à un élément à l’aide de XAML, consultez Comment gérer un événement routé.

Pour attacher un gestionnaire d’événements pour un événement routé à un élément à l’aide de code, vous avez généralement deux options :

  • Appelez directement la AddHandler méthode. Les gestionnaires d’événements routés peuvent toujours être attachés de cette façon. Cet exemple montre comment attacher un gestionnaire d’événements Click à un bouton à l’aide de la AddHandler méthode :

    Button1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    
    Button1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
    

    Pour attacher un gestionnaire pour l’événement du Click bouton à un autre élément de l’itinéraire de l’événement, tel qu’un StackPanel nommé StackPanel1:

    StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    
    StackPanel1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
    
  • Si l’événement routé implémente un wrapper d’événements CLR, utilisez la syntaxe d’événement spécifique au langage pour ajouter des gestionnaires d’événements comme vous le feriez pour un événement CLR standard. La plupart des événements routés WPF existants implémentent le wrapper CLR, ce qui active la syntaxe d’événement spécifique au langage. Cet exemple montre comment attacher un gestionnaire d’événements Click à un bouton à l’aide d’une syntaxe spécifique au langage :

    Button1.Click += Button_Click;
    
    AddHandler Button1.Click, AddressOf Button_Click
    

Pour obtenir un exemple d’attachement d’un gestionnaire d’événements dans le code, consultez Comment ajouter un gestionnaire d’événements à l’aide du code. Si vous codez en Visual Basic, vous pouvez également utiliser l’mot clé Handles pour ajouter des gestionnaires dans le cadre des déclarations de gestionnaire. Pour plus d’informations, consultez gestion des événements Visual Basic et WPF.

Concept de handled

Tous les événements routés partagent une classe de base commune pour les données d’événement, qui est la RoutedEventArgs classe. La RoutedEventArgs classe définit la propriété booléenne Handled . L’objectif de la Handled propriété est de laisser n’importe quel gestionnaire d’événements le long de l’itinéraire d’événements pour marquer l’événement routé comme géré. Pour marquer un événement comme géré, définissez la valeur de celle-ci Handledtrue dans le code du gestionnaire d’événements.

La valeur d’impact Handled sur la façon dont un événement routé est traité quand il se déplace le long de l’itinéraire de l’événement. S’il Handled se trouve true dans les données d’événement partagé d’un événement routé, les gestionnaires attachés à d’autres éléments plus loin le long de l’itinéraire d’événement ne seront généralement pas appelés pour cette instance d’événement particulière. Pour les scénarios de gestionnaire les plus courants, le marquage d’un événement comme géré empêche efficacement les gestionnaires suivants le long de l’itinéraire d’événements, qu’il s’agisse de gestionnaires d’instances ou de classes, de répondre à cette instance d’événement particulière. Toutefois, dans de rares cas où vous avez besoin de votre gestionnaire d’événements pour répondre aux événements routés qui ont été marqués comme gérés, vous pouvez :

Le concept de Handled peut affecter la façon dont vous concevez votre application et codez vos gestionnaires d’événements. Vous pouvez conceptualiser Handled en tant que protocole simple pour le traitement des événements routés. La façon dont vous utilisez ce protocole est à vous, mais l’utilisation attendue du Handled paramètre est :

  • Si un événement routé est marqué comme géré, il n’est pas nécessaire de le gérer à nouveau par d’autres éléments le long de l’itinéraire.

  • Si un événement routé n’est pas marqué comme géré, les écouteurs antérieurs à l’itinéraire d’événement n’ont pas de gestionnaire pour l’événement, ou aucun des gestionnaires inscrits n’a répondu à l’événement d’une manière qui justifie le marquage de l’événement comme géré. Les gestionnaires sur l’écouteur actuel ont trois cours d’action possibles :

    • N’effectuez aucune action du tout. L’événement reste non géré et route vers l’écouteur suivant dans l’arborescence.

    • Exécutez du code en réponse à l’événement, mais pas dans une mesure qui justifie le marquage de l’événement comme géré. L’événement reste non géré et route vers l’écouteur suivant dans l’arborescence.

    • Exécutez du code en réponse à l’événement, dans une mesure qui justifie le marquage de l’événement comme géré. Marquez l’événement comme géré dans les données d’événement. L’événement est toujours acheminé vers l’écouteur suivant dans l’arborescence, mais la plupart des écouteurs n’appellent pas d’autres gestionnaires. L’exception est des écouteurs avec des gestionnaires qui ont été spécifiquement inscrits avec handledEventsToo la valeur définie truesur .

Pour plus d’informations sur la gestion des événements routés, consultez Marquage des événements routés comme gérés et gestion des classes.

Bien que les développeurs qui gèrent uniquement un événement routé en bulle sur l’objet qui a déclenché ne soient pas préoccupés par d’autres écouteurs, il est recommandé de marquer l’événement comme géré de toute façon. Cela empêche les effets secondaires imprévus si un élément plus loin le long de l’itinéraire d’événement a un gestionnaire pour le même événement routé.

Gestionnaires de classes

Les gestionnaires d’événements routés peuvent être des gestionnaires d’instances ou des gestionnaires de classes . Les gestionnaires de classes d’une classe donnée sont appelés avant tout gestionnaire d’instance répondant au même événement sur une instance de cette classe. En raison de ce comportement, lorsque les événements routés sont marqués comme gérés, ils sont souvent marqués comme tels dans les gestionnaires de classes. Il existe deux types de gestionnaires de classes :

  • Gestionnaires d’événements de classe statique, qui sont inscrits en appelant la RegisterClassHandler méthode dans un constructeur de classe statique.
  • Remplacer les gestionnaires d’événements de classe, qui sont inscrits en remplaçant les méthodes d’événements virtuels de classe de base. Les méthodes d’événements virtuels de classe de base existent principalement pour les événements d’entrée et ont des noms qui commencent par le nom> de l’événement On<et le nom> de l’événement OnPreview<.

Certains contrôles WPF ont une gestion de classe inhérente pour certains événements routés. La gestion des classes peut donner l’apparence extérieure que l’événement routé n’est jamais déclenché, mais en réalité, il est marqué comme géré par un gestionnaire de classes. Si vous avez besoin de votre gestionnaire d’événements pour répondre à l’événement géré, vous pouvez inscrire votre gestionnaire avec handledEventsToo la valeur définie truesur . Pour plus d’informations, à la fois sur l’implémentation de vos propres gestionnaires de classes ou sur la gestion des classes non souhaitées, consultez Marquage des événements routés comme gérés et gestion des classes.

Événements joints dans WPF

Le langage XAML définit également un type spécial d’événement appelé événement attaché. Les événements attachés peuvent être utilisés pour définir un nouvel événement routé dans une classe non-élément et déclencher cet événement sur n’importe quel élément de votre arborescence. Pour ce faire, vous devez inscrire l’événement attaché en tant qu’événement routé et fournir un code de stockage spécifique qui prend en charge les fonctionnalités d’événement attachées. Étant donné que les événements joints sont inscrits en tant qu’événements routés, lorsqu’ils sont déclenchés sur un élément qu’ils propagent à travers l’arborescence d’éléments.

Dans la syntaxe XAML, un événement attaché est spécifié par son nom d’événement et son type de propriétaire, sous la forme <owner type>.<event name>. Étant donné que le nom de l’événement est qualifié avec le nom de son type de propriétaire, la syntaxe permet à l’événement d’être attaché à n’importe quel élément pouvant être instancié. Cette syntaxe s’applique également aux gestionnaires pour les événements routés réguliers qui s’attachent à un élément arbitraire le long de l’itinéraire d’événements. Vous pouvez également attacher des gestionnaires pour les événements attachés dans le code-behind en appelant la AddHandler méthode sur l’objet auquel le gestionnaire doit s’attacher.

Le système d’entrée WPF utilise largement les événements attachés. Toutefois, presque tous ces événements attachés sont exposés comme des événements routés non attachés équivalents par le biais d’éléments de base. Vous utiliserez rarement ou gérez directement les événements attachés. Par exemple, il est plus facile de gérer l’événement attaché Mouse.MouseDown sous-jacent sur un UIElement événement routé équivalent UIElement.MouseDown qu’à l’aide de la syntaxe d’événement attachée en XAML ou code-behind.

Pour plus d’informations sur les événements joints dans WPF, consultez la vue d’ensemble des événements joints.

Noms d’événements qualifiés en XAML

La <owner type>.<event name> syntaxe qualifie un nom d’événement avec le nom de son type de propriétaire. Cette syntaxe permet à un événement d’être attaché à n’importe quel élément, pas seulement aux éléments qui implémentent l’événement en tant que membre de leur classe. La syntaxe s’applique lors de l’attachement de gestionnaires en XAML pour les événements attachés ou les événements routés sur des éléments arbitraires le long de l’itinéraire d’événements. Considérez le scénario dans lequel vous souhaitez attacher un gestionnaire à un élément parent afin de gérer les événements routés déclenchés sur les éléments enfants. Si l’élément parent n’a pas l’événement routé en tant que membre, vous devez utiliser la syntaxe du nom d’événement qualifié. Par exemple :

<StackPanel Name="StackPanel1" Button.Click="Button_Click">
    <Button>Click me</Button>
</StackPanel>

Dans l’exemple, l’écouteur d’élément parent auquel le gestionnaire d’événements est ajouté est un StackPanel. Toutefois, l’événement Click routé est implémenté et déclenché sur la ButtonBase classe, et disponible pour la classe via l’héritage Button . Bien que la Button classe « possède » l’événement Click , le système d’événements routé permet aux gestionnaires pour tout événement routé d’être attaché à un UIElement écouteur ou ContentElement à un écouteur d’instance susceptible d’avoir des gestionnaires pour un événement CLR. L’espace de noms par défaut pour ces noms d’attributs d’événements qualifiés est généralement l’espace de noms WPF xmlns par défautxmlns, mais vous pouvez également spécifier des espaces de noms préfixés pour les événements routés personnalisés. Pour plus d’informations sur xmlnsles espaces de noms XAML et le mappage d’espaces de noms pour XAML WPF.

Événements d’entrée WPF

Une application fréquente d’événements routés au sein de la plateforme WPF est destinée aux événements d’entrée. Par convention, les événements routés WPF qui suivent un itinéraire de tunneling ont un nom préfixé par « Preview ». Le préfixe d’aperçu signifie que l’événement d’aperçu se termine avant le démarrage de l’événement de bubbling jumelé. Les événements d’entrée sont souvent fournis en paires, l’un étant un événement d’aperçu et l’autre un événement routé. Par exemple : PreviewKeyDown et KeyDown. Les paires d’événements partagent la même instance de données d’événement, pour lesquelles PreviewKeyDown et KeyDown sont de type KeyEventArgs. Parfois, les événements d’entrée n’ont qu’une version de boublage ou uniquement une version routée directe. Dans la documentation de l’API, les rubriques d’événements routées référencées font référence à des paires d’événements routées et précisent la stratégie de routage pour chaque événement routé.

Les événements d’entrée WPF fournis en paires sont implémentés afin qu’une action utilisateur unique à partir d’un appareil d’entrée, comme une pression sur un bouton de souris, déclenche l’aperçu et les événements routés en séquence. Tout d’abord, l’événement en préversion est déclenché et termine son itinéraire. À la fin de l’événement d’aperçu, l’événement de boublage est déclenché et termine son itinéraire. L’appel RaiseEvent de méthode dans la classe d’implémentation qui déclenche l’événement de basculement réutilise les données d’événement à partir de l’événement d’aperçu pour l’événement de boublage.

Un événement d’entrée en préversion marqué comme géré n’appelle pas de gestionnaires d’événements normalement inscrits pour le reste de l’itinéraire d’aperçu, et l’événement de bubbling jumelé ne sera pas déclenché. Ce comportement de gestion est utile pour les concepteurs de contrôles composites qui souhaitent que les événements d’entrée basés sur les tests de positionnement ou les événements d’entrée basés sur le focus soient signalés au niveau supérieur de leur contrôle. Les éléments de niveau supérieur du contrôle ont la possibilité de gérer les événements en préversion à partir de sous-composants de contrôle afin de les « remplacer » par un événement spécifique au contrôle de niveau supérieur.

Pour illustrer le fonctionnement du traitement des événements d’entrée, tenez compte de l’exemple d’événement d’entrée suivant. Dans l’arborescence suivante, leaf element #2 est la source des PreviewMouseDown événements associés :MouseDown

Event routing diagram.

L’ordre du traitement des événements suivant une action de souris vers le bas sur l’élément feuille #2 est :

  1. PreviewMouseDown événement de tunneling sur l’élément racine.
  2. PreviewMouseDown événement de tunneling sur l’élément intermédiaire #1.
  3. PreviewMouseDown événement de tunneling sur l’élément feuille #2, qui est l’élément source.
  4. MouseDown événement de bulle sur l’élément feuille #2, qui est l’élément source.
  5. MouseDown événement de boublage sur l’élément intermédiaire #1.
  6. MouseDown Événement de boublage sur l’élément racine.

Le délégué du gestionnaire d’événements routés fournit des références à l’objet qui a déclenché l’événement et à l’objet où le gestionnaire a été appelé. L’objet qui a déclenché l’événement à l’origine est signalé par la Source propriété dans les données d’événement. L’objet où le gestionnaire a été appelé est signalé par le paramètre d’expéditeur . Pour une instance d’événement routée donnée, l’objet qui a déclenché l’événement ne change pas à mesure que l’événement se déplace dans l’arborescence d’éléments, mais le sender fait. Dans les étapes 3 et 4 du diagramme précédent, il Sourcesender s’agit du même objet.

Si votre gestionnaire d’événements d’entrée termine la logique propre à l’application nécessaire pour traiter l’événement, vous devez marquer l’événement d’entrée comme géré. En règle générale, une fois qu’un événement d’entrée est marqué Handled, les gestionnaires le long de l’itinéraire d’événement ne sont pas appelés. Toutefois, les gestionnaires d’événements d’entrée inscrits auprès du jeu de handledEventsToo paramètres à true appeler, même lorsque l’événement est marqué comme géré. Pour plus d’informations, consultez Aperçu des événements et marquage des événements routés comme gérés et gestion des classes.

Le concept de paires d’événements de préversion et de bouclage, avec des données d’événement partagées et une levée séquentielle de l’événement d’aperçu, s’applique uniquement à certains événements d’entrée WPF et non à tous les événements routés. Si vous implémentez votre propre événement d’entrée pour résoudre un scénario avancé, envisagez de suivre l’approche de paire d’événements d’entrée WPF.

Si vous implémentez votre propre contrôle composite qui répond aux événements d’entrée, envisagez d’utiliser des événements d’aperçu pour supprimer et remplacer les événements d’entrée déclenchés sur des sous-composants par un événement de niveau supérieur qui représente le contrôle complet. Pour plus d’informations, consultez Marquage des événements routés comme gérés et gestion des classes.

Pour plus d’informations sur le système d’entrée WPF et sur la façon dont les entrées et les événements interagissent dans des scénarios d’application classiques, consultez vue d’ensemble des entrées.

EventSetters et EventTriggers

Dans les styles de balisage, vous pouvez inclure la syntaxe de gestion des événements XAML prédéclarée à l’aide d’un EventSetter. Lorsque le code XAML est traité, le gestionnaire référencé est ajouté à l’instance de style. Vous ne pouvez déclarer qu’un EventSetter événement routé. Dans l’exemple suivant, la méthode de gestionnaire d’événements référencée ApplyButtonStyle est implémentée dans code-behind.

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type Button}">
            <EventSetter Event="Click" Handler="ApplyButtonStyle"/>
        </Style>
    </StackPanel.Resources>
    <Button>Click me</Button>
    <Button Click="Button_Click">Click me</Button>
</StackPanel>

Il est probable que le Style nœud contient déjà d’autres informations de style qui se rapportent aux contrôles du type spécifié et que le fait de faire partie de ces styles favorise la EventSetter réutilisation du code même au niveau du balisage. En outre, un EventSetter nom de méthode abstraite pour les gestionnaires loin de l’application générale et du balisage de page.

Une autre syntaxe spécialisée qui combine l’événement routé et les fonctionnalités d’animation de WPF est un EventTrigger. Comme avec le EventSetter, vous ne pouvez déclarer qu’un EventTrigger événement routé. En règle générale, un EventTrigger est déclaré dans le cadre d’un style, mais il EventTrigger peut être déclaré sur les éléments au niveau de la page dans le cadre de la Triggers collection, ou dans un ControlTemplate. Une EventTrigger option vous permet de spécifier un Storyboard qui s’exécute chaque fois qu’un événement routé atteint un élément dans son itinéraire qui déclare un EventTrigger événement pour cet événement. L’avantage d’une EventTrigger gestion juste de l’événement et de son démarrage d’un storyboard existant est qu’un EventTrigger meilleur contrôle sur le storyboard et son comportement d’exécution. Pour plus d’informations, consultez Utiliser des déclencheurs d’événements pour contrôler un storyboard après son démarrage.

En savoir plus sur les événements routés

Vous pouvez utiliser les concepts et les conseils de cet article comme point de départ lors de la création d’événements routés personnalisés dans vos propres classes. Vous pouvez également prendre en charge vos événements personnalisés avec des classes et délégués de données d’événements spécialisés. Un propriétaire d’événement routé peut être n’importe quelle classe, mais les événements routés doivent être déclenchés par et gérés par des classes dérivées ou ContentElement par UIElement des classes dérivées pour être utiles. Pour plus d’informations sur les événements personnalisés, consultez Créer un événement routé personnalisé.

Voir aussi