Partager via


Vue d’ensemble des événements routés

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.

Conditions préalables

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 auditeurs dans une arborescence d’éléments, pas seulement sur la source de l’é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 une encapsulation d'événement CLR pour permettre de rattacher des gestionnaires dans XAML et dans le 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 :

  • Se propage à travers l'arborescence d'éléments de l'élément d'origine vers l'élément racine, qui est généralement une page ou une fenêtre.
  • Parcourt l’arborescence des éléments de l’élément racine jusqu’à 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é :

Arborescence d’éléments XAML avec trois boutons : Oui, Non et Annuler.

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 remonte du bouton à l’élément racine. Les éléments Button et Border n'ont pas de gestionnaires d’événements attachés, mais StackPanel en a un. Peut-être que d’autres éléments plus haut dans l’arborescence qui ne sont pas affichés ont é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é. Le parcours 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 le RoutedEventArgs.Source dans les paramètres 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 modèle de contenu enrichi. Par exemple, vous pouvez placer une image à l’intérieur d’un Button, ce qui étend efficacement l’arborescence visuelle du bouton. Toutefois, l’image ajoutée ne doit pas altérer le comportement de test de pointage du bouton, qui doit répondre correctement lorsqu’un utilisateur clique sur les pixels de l’image.

  • Points de raccordement des gestionnaires uniques : vous pouvez enregistrer un gestionnaire pour l'événement de chaque bouton, mais avec les é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.

Comment les événements routés sont implémenté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’enregistrement, 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 des accesseurs add et remove pour permettre d'attacher des gestionnaires dans XAML et dans le code-behind via la syntaxe d’événement propre au langage. Les accesseurs add et remove remplacent leur implémentation CLR et appellent les méthodes associées à l’événement routé, AddHandler et RemoveHandler. 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 :

  • 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 : Initialement, les gestionnaires d’événements à 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 aperçu. 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 souvent 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é. Puisque les éléments visuels dérivent de UIElement ou ContentElement, 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 traitent un événement avant 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 de <owner type>.<event name>. Par exemple, étant donné que la classe StackPanel n’implémente pas l’événement Click, pour attacher un gestionnaire à un événement StackPanel de Click qui remonte 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 délégué DragEventHandler. Ainsi, votre code de gestionnaire peut accéder à la propriété DragEventArgs.Data dans les données d’événement, qui contient la charge utile du Presse-papiers résultant de l’opération de glisser-déposer.

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 d'événement du Click bouton à un autre élément sur le chemin 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 le Handles mot clé pour ajouter des gestionnaires dans le cadre des déclarations de gestionnaire. Pour plus d’informations, consultez traitement des événements dans Visual Basic et WPF.

Concept de manipulable

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 permettre à n’importe quel gestionnaire d’événements le long du parcours d’événements de 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 de Handled influence la manière dont un événement routé est traité lorsqu'il progresse le long de son itinéraire. S'il Handled se trouve true dans les données partagées d'un événement routé, les gestionnaires attachés à d'autres éléments plus loin sur le parcours de l'événement ne seront généralement pas invoqué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 de l'auditeur actuel ont trois options possibles :

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

    • Exécutez du code en réponse à l'événement, mais pas au point de justifier de marquer l'événement comme traité. L’événement reste non géré et est dirigé 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 transmis à l’écouteur suivant dans l’arborescence, mais la plupart des écouteurs ne déclenchent pas d’autres gestionnaires. L'exception concerne les auditeurs avec des gestionnaires qui ont été spécifiquement enregistrés avec handledEventsToo défini sur true.

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 situé plus loin sur le parcours de l'é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 :

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 que votre gestionnaire d’événements réponde à l’événement géré, vous pouvez enregistrer votre gestionnaire avec handledEventsToo, en réglant true sur la valeur définie. 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 soutien spécifique prenant en charge les fonctionnalités d’événement attaché. Puisque les événements attachés sont enregistrés en tant qu’événements routés, lorsqu’ils sont déclenchés sur un élément, ils se 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 la route d’événements. Vous pouvez également attacher des gestionnaires pour les événements attachés dans le code-behind en appelant la méthode AddHandler 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 sous-jacent attaché Mouse.MouseDown sur un UIElement via l’événement routé UIElement.MouseDown équivalent que d'utiliser la syntaxe d’événement attachée en XAML ou dans le 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 classe ButtonBase, et accessible à la classe Button via l’héritage. Bien que la Button classe « possède » l’événement Click, le système d’événements routés permet à tout gestionnaire d’événement routé d’être attaché à un écouteur d’instance UIElement ou ContentElement pouvant avoir des gestionnaires pour un événement CLR. L'espace de noms par défaut xmlns pour ces noms d'attributs d'événements qualifiés est généralement l'espace de noms WPF par défaut xmlns, 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 xmlns, consultez les espaces de noms XAML et le mappage des espaces de noms pour le 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

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

Un événement d'entrée de prévisualisation marqué comme géré n'appellera pas de gestionnaires d'événements normalement inscrits pour le reste du parcours de prévisualisation, et l'événement de propagation 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

Diagramme montrant comment le routage des événements passe d’un élément racine à d’autres éléments.

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 d’aperçu et de bouillonnement, avec des données d’événement partagées et une levée séquentielle d’abord de l’événement d’aperçu, puis de l’événement de bouillonnement, 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 stylée. 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 isole les noms des méthodes des gestionnaires de l'application générale et du balisage des pages.

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 pour un é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 pour cet événement. L’avantage d’un EventTrigger par rapport à simplement gérer l’événement et déclencher un storyboard existant, est qu’un EventTrigger offre un 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 soutenir vos événements personnalisés avec des classes de données d’événements spécialisées et des délégué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 UIElement ou ContentElement et gérés par 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