Partager via


Extensions de balisage et XAML WPF

Cette rubrique présente le concept d’extensions de balisage pour XAML, notamment leurs règles de syntaxe, leur objectif et le modèle objet de classe qui les sous-tend. Les extensions de balisage sont une fonctionnalité générale du langage XAML et de l’implémentation .NET des services XAML. Cette rubrique détaille spécifiquement les extensions de balisage à utiliser dans LE code XAML WPF.

Processeurs XAML et extensions de balisage

En règle générale, un analyseur XAML peut interpréter une valeur d’attribut en tant que chaîne littérale qui peut être convertie en primitive, ou la convertir en objet par certains moyens. L’un de ces moyens consiste à référencer un convertisseur de type ; ceci est documenté dans la rubrique TypeConverters etXAML. Toutefois, il existe des scénarios où différents comportements sont requis. Par exemple, un processeur XAML peut être invité à indiquer qu’une valeur d’un attribut ne doit pas entraîner de nouvel objet dans le graphe d’objets. Au lieu de cela, l’attribut doit entraîner un graphique d’objet qui fait référence à un objet déjà construit dans une autre partie du graphique ou un objet statique. Un autre scénario est qu’un processeur XAML peut être invité à utiliser une syntaxe qui fournit des arguments non par défaut au constructeur d’un objet. Il s’agit des types de scénarios où une extension de balisage peut fournir la solution.

Syntaxe d’extension de balisage de base

Une extension de balisage peut être implémentée pour fournir des valeurs pour les propriétés dans l’utilisation d’un attribut, les propriétés d’une utilisation d’un élément de propriété ou les deux.

Quand elle est utilisée pour fournir une valeur d’attribut, la syntaxe qui distingue une séquence d’extension de balisage d’un processeur XAML est la présence d’accolades ouvrantes et fermantes ({ et }). Le type d’extension de balisage est alors identifié par le jeton de chaîne qui suit immédiatement l’accolade ouvrante.

Lorsqu’elle est utilisée dans la syntaxe de l’élément de propriété, une extension de balisage est visuellement identique à tout autre élément utilisé pour fournir une valeur d’élément de propriété : déclaration d’élément XAML qui référence la classe d’extension de balisage en tant qu’élément, placé entre crochets angle (<>).

Extensions de balisage XAML-Defined

Plusieurs extensions de balisage existent qui ne sont pas spécifiques à l’implémentation WPF de XAML, mais sont plutôt des implémentations d’intrinsèques ou de fonctionnalités xaml en tant que langage. Ces extensions de balisage sont implémentées dans l’assembly System.Xaml dans le cadre des services XAML .NET Framework généraux et se trouvent dans l’espace de noms XAML du langage XAML. En termes d’utilisation courante des balisages, ces extensions de balisage sont généralement identifiables par le préfixe x: dans l’utilisation. La classe de base MarkupExtension (également définie dans System.Xaml) fournit le modèle que toutes les extensions de balisage doivent utiliser pour être prises en charge dans les lecteurs XAML et les enregistreurs XAML, y compris dans WPF XAML.

  • x:Type fournit l’objet Type pour le type nommé. Cette fonctionnalité est utilisée le plus fréquemment dans les styles et les modèles. Pour plus d’informations, consultez Extension de balisage x:Type.

  • x:Static produit des valeurs statiques. Les valeurs proviennent d’entités de code de type valeur qui ne sont pas directement le type de la valeur d’une propriété cible, mais peuvent être évaluées à ce type. Pour plus d'informations, consultez l'extension de balisage x:Static .

  • x:Null spécifie null comme valeur pour une propriété et peut être utilisée pour les attributs ou les valeurs d’élément de propriété. Pour plus d’informations, consultez Extension de balisage "x:Null".

  • x:Array prend en charge la création de tableaux généraux dans la syntaxe XAML, dans les cas où la prise en charge de la collection fournie par les éléments de base et les modèles de contrôle WPF n’est délibérément pas utilisée. Pour plus d’informations, consultez Extension de balisage x:Array.

Note

Le préfixe x: est utilisé pour le mappage d’espace de noms XAML standard des intrinsèques du langage XAML, dans l’élément racine d’un fichier ou d’une production XAML. Par exemple, les modèles Visual Studio pour les applications WPF lancent un fichier XAML à l’aide de ce mappage x:. Vous pouvez choisir un autre jeton de préfixe dans votre propre mappage d’espace de noms XAML, mais cette documentation suppose le mappage par défaut x: comme moyen d’identifier les entités qui sont une partie définie de l’espace de noms XAML pour le langage XAML, par opposition à l’espace de noms WPF par défaut ou à d’autres espaces de noms XAML non liés à une infrastructure spécifique.

Extensions de balisage WPF-Specific

Les extensions de balisage les plus courantes utilisées dans la programmation WPF sont celles qui prennent en charge les références de ressources (StaticResource et DynamicResource), et celles qui prennent en charge la liaison de données (Binding).

  • StaticResource fournit une valeur pour une propriété en remplaçant la valeur d’une ressource déjà définie. Une évaluation StaticResource est finalement effectuée au moment du chargement XAML et n’a pas accès au graphe d’objets au moment de l’exécution. Pour plus d’informations, consultez StaticResource Markup Extension.

  • DynamicResource fournit une valeur de propriété en différant le moment où cette valeur devient une référence à une ressource au moment de l’exécution. Une référence de ressource dynamique force une nouvelle recherche chaque fois qu’une telle ressource est accessible et a accès au graphique d’objet au moment de l’exécution. Pour obtenir cet accès, le concept DynamicResource est pris en charge par les propriétés de dépendance dans le système de propriétés WPF et les expressions évaluées. Par conséquent, vous pouvez uniquement utiliser DynamicResource pour une cible de propriété de dépendance. Pour plus d’informations, consultez Extension de balisage DynamicResource.

  • Binding fournit une valeur liée aux données pour une propriété, à l’aide du contexte de données qui s’applique à l’objet parent au moment de l’exécution. Cette extension de balisage est relativement complexe, car elle permet une syntaxe inline substantielle pour spécifier une liaison de données. Pour plus d’informations, consultez Extension de balisage Liaison.

  • RelativeSource fournit des informations sources pour un Binding qui peut parcourir plusieurs relations possibles dans l’arborescence d’objets d’exécution. Cela fournit un approvisionnement spécialisé pour les liaisons créées dans des modèles multi-utilisation ou créées dans du code sans connaissance complète de l’arborescence d’objets environnante. Pour plus d’informations, consultez RelativeSource MarkupExtension.

  • TemplateBinding permet à un modèle de contrôle d’utiliser des valeurs pour les propriétés modélisées qui proviennent des propriétés définies par le modèle objet de la classe qui utiliseront le modèle. En d’autres termes, la propriété dans la définition de modèle peut accéder à un contexte qui existe uniquement une fois que le modèle est appliqué. Pour plus d’informations, consultez Extension de balisage TemplateBinding. Pour plus d’informations sur l’utilisation pratique de TemplateBinding, consultez l’exemple de mise en forme avec les ControlTemplates.

  • ColorConvertedBitmap prend en charge un scénario d’imagerie relativement avancé. Pour plus d’informations, consultez Extension de balisage ColorConvertedBitmap.

  • ComponentResourceKey et ThemeDictionary prennent en charge les aspects de la recherche de ressources, en particulier pour les ressources et les thèmes empaquetés avec des contrôles personnalisés. Pour plus d’informations, consultez componentResourceKey Markup Extension, ThemeDictionary Markup Extensionou Control Authoring Overview.

*Classes d’extension

Pour le langage XAML général et les extensions de balisage propres à WPF, le comportement de chaque extension de balisage est identifié à un processeur XAML par le biais d’une classe *Extension qui dérive de MarkupExtensionet fournit une implémentation de la méthode ProvideValue. Cette méthode sur chaque extension fournit l’objet retourné lorsque l’extension de balisage est évaluée. L’objet retourné est généralement évalué en fonction des différents jetons de chaîne transmis à l’extension de balisage.

Par exemple, la classe StaticResourceExtension fournit l’implémentation de surface pour la recherche de ressources réelles afin que son implémentation ProvideValue retourne l’objet demandé, l’entrée de cette implémentation particulière étant une chaîne utilisée pour rechercher la ressource par son x:Key. La plupart de ces détails d’implémentation ne sont pas importants si vous utilisez une extension de balisage existante.

Certaines extensions de balisage n’utilisent pas d’arguments de jeton de chaîne. Cela est dû au fait qu’ils retournent une valeur statique ou cohérente, ou parce que le contexte de la valeur à retourner est disponible via l’un des services transmis par le paramètre serviceProvider.

Le modèle de nommage *Extension est pratique et cohérent. Il n’est pas nécessaire pour qu’un processeur XAML identifie cette classe comme prise en charge d’une extension de balisage. Tant que votre codebase inclut System.Xaml et utilise des implémentations de services XAML .NET Framework, tout ce qui est nécessaire pour être reconnu comme une extension de balisage XAML consiste à dériver de MarkupExtension et à prendre en charge une syntaxe de construction. WPF définit les classes d’activation de l’extension de balisage qui ne suivent pas le modèle d’affectation de noms *Extension, par exemple Binding. En règle générale, la raison en est que la classe prend en charge des scénarios au-delà de la prise en charge pure de l’extension de balisage. Dans le cas de Binding, cette classe prend en charge l’accès au moment de l’exécution aux méthodes et aux propriétés de l’objet pour les scénarios qui n’ont rien à voir avec XAML.

Interprétation du texte d’initialisation par la classe d’extension

Les jetons de chaîne situés à la suite du nom d’extension de balisage et se trouvant toujours entre accolades sont interprétés par un processeur XAML de l’une des manières suivantes :

  • Une virgule représente toujours le séparateur ou le délimiteur des jetons individuels.

  • Si les jetons séparés individuels ne contiennent aucun signe égal, chaque jeton est traité comme un argument de constructeur. Chaque paramètre de constructeur doit être donné comme type attendu par cette signature, et dans l’ordre approprié attendu par cette signature.

    Note

    Un processeur XAML doit appeler le constructeur dont le nombre d'arguments correspond au nombre de paires. Pour cette raison, si vous implémentez une extension de balisage personnalisée, ne fournissez pas plusieurs constructeurs avec le même nombre d’arguments. Le comportement d'un processeur XAML dans le cas où plusieurs chemins de constructeur d'extension de balisage ayant le même nombre de paramètres existent n'est pas défini, mais vous devez anticiper qu'un processeur XAML est autorisé à lancer une exception lors de l'utilisation si cette situation existe dans les définitions de type d'extension de balisage.

  • Si les jetons séparés individuels contiennent des signes égaux, un processeur XAML appelle d’abord le constructeur sans paramètre pour l’extension de balisage. Ensuite, chaque paire name=value est interprétée comme un nom de propriété qui existe sur l’extension de balisage et une valeur à affecter à cette propriété.

  • S’il existe un résultat parallèle entre le comportement du constructeur et le comportement du paramètre de propriété dans une extension de balisage, il n’importe pas quel comportement vous utilisez. Il est plus courant d'utiliser les paires de valeurs de propriété =valeur pour les extensions de balisage qui ont plus d'une propriété réglable, ne serait-ce que parce que cela rend votre balisage plus intentionnel et que vous êtes moins susceptible de transposer accidentellement des paramètres de constructeur. (Lorsque vous spécifiez des paires property=value, ces propriétés peuvent être dans n’importe quel ordre.) En outre, il n’existe aucune garantie qu’une extension de balisage fournit un paramètre de constructeur qui définit chacune de ses propriétés settables. Par exemple, Binding est une extension de balisage, avec de nombreuses propriétés qui sont définissables via l'extension sous la forme propriété=valeur, mais Binding ne prend en charge que deux constructeurs : un constructeur sans paramètre et un qui définit un chemin initial.

  • Une virgule littérale ne peut pas être passée à une extension de balisage sans échappement.

Séquences d’échappement et extensions de balisage

La gestion des attributs dans un processeur XAML utilise les accolades comme indicateurs d’une séquence d’extension de balisage. Il est possible aussi de générer une valeur d’attribut de caractère d’accolade littérale, si nécessaire, en entrant une séquence d’échappement avec une paire d’accolades vides, suivie de l’accolade littérale. Consultez {} Séquence d’échappement - Extension de balisage.

Imbrication d’extensions de balisage dans l’utilisation de XAML

L’imbrication de plusieurs extensions de balisage est prise en charge, et chaque extension de balisage est d’abord évaluée au plus profond. Par exemple, considérez l’utilisation suivante :

<Setter Property="Background"  
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />  

Dans cette utilisation, l’instruction x:Static est évaluée en premier et retourne une chaîne. Cette chaîne est ensuite utilisée comme argument pour DynamicResource.

Syntaxe des extensions de balisage et des éléments de propriété

Lorsqu'elle est utilisée comme élément d'objet qui remplit une valeur d'élément de propriété, une classe d'extension de balisage est visuellement indistinguable d'un élément d'objet soutenu par un type classique pouvant être utilisé en XAML. La différence pratique entre un élément objet classique et une extension de balisage est que l’extension de balisage est évaluée à une valeur typée ou différée en tant qu’expression. Par conséquent, les mécanismes qui interviennent en cas d’erreur de type pour les valeurs de propriété de l’extension de balisage sont différents, à l’instar de la façon dont une propriété à liaison tardive est traitée dans d’autres modèles de programmation. Un élément objet ordinaire est évalué pour la correspondance de type par rapport à la propriété cible qu’il définit lorsque le code XAML est analysé.

La plupart des extensions de balisage, lorsqu’elles sont utilisées dans la syntaxe de l’élément objet pour remplir un élément de propriété, n’auraient pas de contenu ni de syntaxe d’élément de propriété supplémentaire. Par conséquent, vous devez fermer la balise de l’élément objet et ne fournir aucun élément enfant. Chaque fois qu’un élément objet est rencontré par un processeur XAML, le constructeur de cette classe est appelé, qui instancie l’objet créé à partir de l’élément analysé. Une classe d’extension de balisage n’est pas différente : si vous souhaitez que votre extension de balisage soit utilisable dans la syntaxe des éléments d’objet, vous devez fournir un constructeur sans paramètre. Certaines extensions de balisage existantes ont au moins une valeur de propriété requise qui doit être spécifiée pour une initialisation effective. Si c’est le cas, cette valeur de propriété est généralement donnée en tant qu’attribut de propriété sur l’élément objet. Les extensions de balisage qui ont des propriétés requises (et les noms de ces propriétés) sont notées dans les pages de référence Fonctionnalités de langage pour les espaces de noms XAML (x:) et Extensions XAML WPF. Les pages de référence notent également si la syntaxe de l’élément objet ou la syntaxe d’attribut est interdite pour des extensions de balisage particulières. Un cas notable est x :Array Markup Extension, qui ne peut pas prendre en charge la syntaxe d’attribut, car le contenu de ce tableau doit être spécifié dans le balisage en tant que contenu. Le contenu du tableau est géré en tant qu’objets généraux. Par conséquent, aucun convertisseur de type par défaut pour l’attribut n’est possible. De plus, l’extension de balisage x:Array nécessite un paramètre type.

Voir aussi