Vue d'ensemble des événements attachés
Extensible Application Markup Language (XAML) 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 réellement l'événement ou qui en hérite. Dans ce cas, ni l'objet qui déclenche potentiellement l'événement ni l'instance de gestion de destination ne définit ou "possède" l'événement.
Cette rubrique comprend les sections suivantes.
- Composants requis
- Syntaxe d'événement attaché
- Comment WPF implémente des événements attachés
- Scénarios pour les événements attachés
- Gestion d'un événement attaché dans WPF
- Définition de vos propres événements attachés comme événements routés
- Déclenchement d'un événement WPF attaché
- Rubriques connexes
Composants requis
Cette rubrique suppose que vous avez lu Vue d'ensemble des événements routés et Vue d'ensemble du langage XAML (WPF).
Syntaxe d'événement attaché
Les événements attachés ont une syntaxe XAML et un modèle de codage qui doivent être utilisés par le code de stockage afin de 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 aussi par son type propriétaire, les deux étant séparés par un point (.). Comme le nom de l'évènement est qualifié avec le nom de son type propriétaire, la syntaxe de l'événement attaché permet à celui-ci d'être attaché à tout élément pouvant être instancié.
Par exemple, vous trouverez ci-dessous la syntaxe XAML requise pour joindre un gestionnaire pour un événement attaché NeedsCleaning personnalisé :
<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>
Notez le préfixe aqua:; ce préfixe est nécessaire dans ce cas parce que l'événement attaché est un événement personnalisé qui provient d'un fichier xmlns mappé personnalisé.
Comment WPF implémente des événements attachés
Dans WPF, les événements attachés sont stockés par un champ RoutedEvent et sont routés à travers l'arborescence après leur déclenchement. En général, la source de l'événement attaché (l'objet qui déclenche l'événement) est une source système ou de service, et l'objet qui exécute le code qui déclenche l'événement ne fait pas par conséquent directement partie de l'arborescence d'éléments.
Scénarios pour les événements attachés
Dans WPF, les événements attachés sont présent dans certaines fonctionnalités où figure l'abstraction de niveau de service, comme pour les événements activés par la classe statique Mouse ou la classe Validation. Les classes qui interagissent avec le service ou qui l'utilisent peuvent utiliser l'événement dans la syntaxe d'événement attaché, ou choisir de surfacer l'événement attaché comme un événement routé faisant partie de la manière dont la classe intègre les fonctionnalités du service.
Bien que WPF définisse plusieurs événements attachés, les scénarios où vous utiliserez ou gérerez directement l'événement attaché sont très limités. En général, l'objet de l'événement attaché est architectural, mais il est ensuite transmis à un événement routé non attaché (stocké avec un wrapper d'événement CLR).
Par exemple, l'événement Mouse.MouseDown attaché sous-jacent peut être plus facilement géré sur tout UIElement donné en utilisant MouseDown sur ce UIElement plutôt que de se servir de la syntaxe d'événement attaché dans XAML ou dans le code. L'événement attaché a une fonction dans l'architecture parce qu'il permet dans l'avenir une extension des périphériques d'entrée. Le périphérique hypothétique n'aurait qu'à déclencher Mouse.MouseDown pour simuler une entrée par le biais de la souris et n'aurait pas besoin de dériver de Mouse pour ce faire. Toutefois, ce scénario implique une gestion du code des événements, et une 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 le code du gestionnaire que vous écrirez, est essentiellement le même que pour 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 portent sur la manière dont l'événement est alimenté et comment il est exposé par une classe comme un membre (ce qui affecte également la syntaxe du gestionnaire XAML).
Toutefois, comme noté précédemment, les événements attachés WPF existants ne sont pas prévus en particulier pour une gestion dans WPF. Plus souvent, le but de l'événement est de permettre à un élément composé 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 compte également sur la gestion de classe dans la classe parente pertinente. Par exemple, les éléments dans un Selector sont supposés déclencher l'événement Selected attaché, qui est ensuite géré par classe par la classe Selector , puis potentiellement converti par la classe Selector en un événement routé différent, SelectionChanged. Pour plus d'informations sur les événements routés la et gestion de classe, consultez Marquage des événements routés comme gérés et gestion de classe.
Définition de vos propres événements attachés comme événements routés
Si vous dérivez de classes de base WPF communes, 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 Add*Handler avec deux paramètres. Le premier paramètre doit identifier l'événement, et l'événement identifié doit correspondre aux noms avec le * dans le nom de méthode. Le second paramètre est le gestionnaire à ajouter. La méthode doit être publique et statique, sans valeur de retour.
Une méthode Remove*Handler avec deux paramètres. Le premier paramètre doit identifier l'événement, et l'événement identifié doit correspondre aux noms avec le * dans le nom de méthode. Le second paramètre est le gestionnaire à supprimer. La méthode doit être publique et statique, sans valeur de retour.
La méthode d'accesseur Add*Handler facilite le traitement XAML lorsque les attributs de gestionnaire d'événements attachés sont déclarés sur un élément. Les méthodes Add*Handler et Remove*Handler activent également l'accès du code au magasin de gestionnaires d'événements pour l'événement attaché.
Ce modèle général n'est pas encore assez précis pour une implémentation pratique dans une infrastructure, parce que toute implémentation donnée de lecteur XAML peut avoir des méthodes différentes pour identifier des é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 les événements attachés comme des événements routés ; l'identificateur à utiliser pour un événement (RoutedEvent) est déjà défini par le système d'événement WPF. De plus, router un événement est une extension d'implémentation naturelle sur le concept de niveau de langage XAML d'un événement attaché.
L'implémentation de Add*Handler pour un événement WPF attaché consiste à appeler le AddHandler avec l'événement routé et le gestionnaire comme arguments.
Cette stratégie d'implémentation et le système d'événement routé en général restreignent la gestion pour les événements attachés aux classes dérivées UIElement ou ContentElement, parce que 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 qui consiste à déclarer l'événement attaché comme un événement routé.
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
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);
}
}
Notez que la méthode utilisée pour établir le champ de l'identificateur de l'événement attaché, RegisterRoutedEvent, est en fait la même méthode que celle utilisée pour enregistrer un événement routé non attaché. Les événements attachés et les événements routés sont tous enregistrés dans un magasin interne centralisé. Cette implémentation du magasin d'événements active la considération conceptuelle "événements comme une interface" traitée dans Vue d'ensemble des événements routés.
Déclenchement d'un événement WPF attaché
Vous n'avez généralement pas besoin de déclencher des événements attachés définis par WPF à partir de votre code. Ces événements suivent le modèle conceptuel général de "service", et des classes de service telles que InputManager sont chargées de déclencher les événements.
Toutefois, si vous définissez un événement attaché personnalisé basé sur le modèle WPF qui consiste à baser des événements attachés sur RoutedEvent, vous pouvez utiliser RaiseEvent pour déclencher un événement attaché à partir de tout 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 comme source de l'événement ; cette source est signalée comme appelant RaiseEvent. Il incombe à votre service de déterminer quel élément est signalé comme source dans l'arborescence.