Vue d’ensemble des événements joints
Le langage XAML (Extensible Application Markup Language) définit un composant de langage et un type d’événement appelé événement attaché. Le concept d’un événement attaché vous permet d’ajouter un gestionnaire pour un événement particulier à un élément arbitraire plutôt qu’à un élément qui définit ou hérite réellement de l’événement. Dans ce cas, ni l'objet susceptible de déclencher l'événement ni l'instance de destination qui le gère ne définit ou ne « possède » l'événement.
Conditions préalables
Cette rubrique part du principe que vous avez lu vue d’ensemble des événements routés et XAML dans WPF.
Syntaxe de l’événement attaché
Les événements attachés ont une syntaxe XAML et un modèle de codage qui doit être utilisé par le code de stockage pour prendre en charge l’utilisation des événements attachés.
Dans la syntaxe XAML, l’événement attaché est spécifié non seulement par son nom d’événement, mais par son type propriétaire plus le nom de l’événement, séparé par un point (.). Étant donné que le nom de l’événement est qualifié avec le nom de son type propriétaire, la syntaxe de l’événement attaché permet à tout événement attaché d’être attaché à n’importe quel élément pouvant être instancié.
Par exemple, voici la syntaxe XAML permettant d’attacher un gestionnaire pour un événement personnalisé NeedsCleaning
attaché :
<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>
Notez le préfixe aqua:
; le préfixe est nécessaire dans ce cas, car l’événement attaché est un événement personnalisé provenant d’un xmlns mappé personnalisé.
Comment WPF implémente les événements attachés
Dans WPF, les événements joints sont soutenus par un champ RoutedEvent et sont routés via l’arborescence une fois qu’ils sont déclenchés. En règle générale, la source de l’événement attaché (l’objet qui déclenche l’événement) est une source de système ou de service, et l’objet qui exécute le code qui déclenche l’événement n’est donc pas une partie directe de l’arborescence d’éléments.
Scénarios pour les événements attachés
Dans WPF, les événements joints sont présents dans certaines zones de fonctionnalités où il existe une abstraction au niveau du service, par exemple pour les événements activés par la classe de Mouse statique ou la classe Validation. Les classes qui interagissent avec ou utilisent le service peuvent utiliser l’événement dans la syntaxe d’événement jointe, ou elles peuvent choisir d’exposer l’événement attaché en tant qu’événement routé qui fait partie de la façon dont la classe intègre les fonctionnalités du service.
Bien que WPF définit un certain nombre d’événements attachés, les scénarios dans lesquels vous allez utiliser ou gérer directement l’événement attaché sont très limités. En règle générale, l’événement attaché a une fonction architecturale, mais est ensuite transmis à un événement routé non attaché encapsulé dans un événement CLR « wrapper ».
Par exemple, l’événement attaché sous-jacent Mouse.MouseDown peut être plus facilement géré sur n’importe quelle UIElement donnée à l’aide d'MouseDown sur cette UIElement plutôt que de traiter la syntaxe d’événement attachée en XAML ou en code. L’événement attaché sert d’objectif dans l’architecture, car il permet l’expansion future des périphériques d’entrée. L’appareil hypothétique n’aurait besoin que d’élever Mouse.MouseDown pour simuler l’entrée de la souris, et n’aurait pas besoin de dériver de Mouse pour le faire. Toutefois, ce scénario implique la gestion du code des événements et la gestion XAML de l’événement attaché n’est pas pertinente pour ce scénario.
Gestion d’un événement attaché dans WPF
Le processus de gestion d’un événement attaché et du code de gestionnaire que vous allez écrire est essentiellement identique à celui d’un événement routé.
En général, un événement attaché WPF n’est pas très différent d’un événement routé WPF. Les différences sont la source de l’événement et la façon dont il est exposé par une classe en tant que membre (qui affecte également la syntaxe du gestionnaire XAML).
Toutefois, comme indiqué précédemment, les événements joints WPF existants ne sont pas particulièrement destinés à la gestion dans WPF. Plus souvent, l’objectif de l’événement est de permettre à un élément composite de signaler un état à un élément parent dans la composition, auquel cas l’événement est généralement déclenché dans le code et s’appuie également sur la gestion des classes dans la classe parente appropriée. Par exemple, les éléments d’une Selector sont censés déclencher l’événement Selected correspondant, qui est ensuite manipulé par la classe Selector, puis éventuellement converti par la classe Selector en un autre événement routé, SelectionChanged. Pour plus d’informations sur les événements routés et la gestion des classes, consultez Marquage des Événements Routés comme Traités et Gestion des Classes.
Définir vos propres événements attachés comme événements routés
Si vous dérivez de classes de base WPF courantes, vous pouvez implémenter vos propres événements attachés en incluant certaines méthodes de modèle dans votre classe et en utilisant des méthodes utilitaires déjà présentes sur les classes de base.
Le modèle est le suivant :
Une méthode AddEventNameHandler avec deux paramètres. Le premier paramètre est l’instance à laquelle le gestionnaire d’événements est ajouté. Le deuxième paramètre est le gestionnaire d’événements à ajouter. La méthode doit être
public
etstatic
, sans valeur de retour.Une méthode RemoveEventNameHandler avec deux paramètres. Le premier paramètre est l’instance à partir de laquelle le gestionnaire d’événements est supprimé. Le deuxième paramètre est le gestionnaire d’événements à supprimer. La méthode doit être
public
etstatic
, sans valeur de retour.
La méthode d'accesseur AddEventNameHandler facilite le traitement du XAML lorsque des attributs de gestionnaire d’événements attachés sont déclarés sur un élément. Les méthodes AddEventNameHandler et RemoveEventNameHandler permettent également au code d'accéder au magasin de gestionnaires d'événements pour l'événement attaché.
Ce modèle général n’est pas encore suffisamment précis pour l’implémentation pratique dans un framework, car toute implémentation de lecteur XAML donnée peut avoir des schémas différents pour identifier les événements sous-jacents dans le langage et l’architecture de prise en charge. C’est l’une des raisons pour lesquelles WPF implémente des événements attachés en tant qu’événements routés ; l’identificateur à utiliser pour un événement (RoutedEvent) est déjà défini par le système d’événements WPF. En outre, le routage d’un événement est une extension d’implémentation naturelle sur le concept de langage XAML d’un événement attaché.
L’implémentation AddEventNameHandler pour un événement attaché WPF consiste à appeler le AddHandler avec l’événement routé et le gestionnaire en tant qu’arguments.
Cette stratégie d’implémentation et le système d’événements routés en général limitent la gestion des événements attachés aux classes dérivées UIElement ou ContentElement, car seules ces classes possèdent des implémentations AddHandler.
Par exemple, le code suivant définit l’événement attaché NeedsCleaning
sur la classe propriétaire Aquarium
, à l’aide de la stratégie d’événement attaché WPF pour déclarer l’événement attaché en tant qu’événement routé.
public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
Public Shared ReadOnly NeedsCleaningEvent As RoutedEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
Public Shared Sub AddNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
Dim uie As UIElement = TryCast(d, UIElement)
If uie IsNot Nothing Then
uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler)
End If
End Sub
Public Shared Sub RemoveNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
Dim uie As UIElement = TryCast(d, UIElement)
If uie IsNot Nothing Then
uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler)
End If
End Sub
Notez que la méthode utilisée pour établir le champ d’identificateur d’événement attaché, RegisterRoutedEvent, est en fait la même méthode que celle utilisée pour inscrire un événement routé non attaché. Les événements attachés et les événements routés sont tous enregistrés dans un dépôt interne centralisé. Cette implémentation de magasin d’événements active la considération conceptuelle « événements en tant qu’interface » décrite dans Vue d’ensemble des événements routés.
Déclenchement d’un événement attaché WPF
En règle générale, vous n’avez pas besoin de déclencher des événements joints définis par WPF existants à partir de votre code. Ces événements suivent le modèle conceptuel « service » général et les classes de service telles que InputManager sont responsables du déclenchement des événements.
Toutefois, si vous définissez un événement attaché personnalisé basé sur le modèle WPF de base des événements attachés sur RoutedEvent, vous pouvez utiliser RaiseEvent pour déclencher un événement attaché à partir de n’importe quel UIElement ou ContentElement. Le déclenchement d’un événement routé (attaché ou non) nécessite que vous déclariez un élément particulier dans l’arborescence d’éléments en tant que source d’événement ; cette source est signalée comme appelant RaiseEvent. Déterminer quel élément est signalé comme source dans l’arborescence est la responsabilité de votre service
Voir aussi
- Vue d’ensemble des événements routés
- Syntaxe XAML en détail
- XAML et classes personnalisées pour WPF
.NET Desktop feedback