Partager via


Vue d’ensemble des extensions de balisage pour XAML

Les extensions de balisage sont une technique XAML permettant d’obtenir une valeur qui n’est pas une primitive ou un type XAML spécifique. Pour l'utilisation des attributs, les extensions de balisage utilisent la séquence de caractères connue d'une accolade ouvrante { pour entrer dans l'étendue de l'extension de balisage, et une accolade fermante } pour quitter. Lorsque vous utilisez les services XAML .NET, vous pouvez utiliser certaines des extensions de balisage de langage XAML prédéfinies à partir de l’assembly System.Xaml. Vous pouvez également hériter de la classe MarkupExtension, définie dans System.Xaml, et y définir vos propres extensions de balisage. Vous pouvez également utiliser des extensions de balisage définies par une infrastructure particulière si vous référencez déjà cette infrastructure.

Lorsqu’une utilisation de l’extension de balisage est accessible, l’enregistreur d’objets XAML peut fournir des services à une classe de MarkupExtension personnalisée via un point de connexion de service dans le remplacement MarkupExtension.ProvideValue. Les services peuvent être utilisés pour obtenir le contexte sur l’utilisation, les fonctionnalités spécifiques de l’enregistreur d’objets, le contexte de schéma XAML, et ainsi de suite.

Extensions de balisage définies par XAML

Plusieurs extensions de balisage sont implémentées par les services XAML .NET pour la prise en charge du langage XAML. Ces extensions de balisage correspondent à certaines parties de la spécification xaml en tant que langage. Ils sont généralement identifiables par le préfixe x: dans la syntaxe, comme indiqué dans l’utilisation courante. Les implémentations des services XAML .NET pour ces éléments de langage XAML dérivent toutes de la classe de base MarkupExtension.

Note

Le préfixe x: est utilisé pour le mappage classique de l'espace de noms du langage XAML dans l'élément racine d'une structure XAML. Par exemple, les modèles de projet et de page Visual Studio pour différents frameworks initient 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 ces entités qui sont une partie définie de l’espace de noms XAML du langage XAML, par opposition à l’espace de noms XAML par défaut d’un framework spécifique ou à d’autres espaces de noms CLR ou XML arbitraires.

x:Type

x:Type fournit l’objet Type pour le type nommé. Cette fonctionnalité est le plus souvent utilisée dans les mécanismes de report qui emploient le type CLR sous-jacent et la dérivation de type comme nom ou identificateur de regroupement. Les styles et les modèles WPF, ainsi que leur utilisation des propriétés TargetType, sont un exemple spécifique. Pour plus d’informations, consultez extension de balisage x :Type.

x:Static

x:Static produit des valeurs statiques à partir d’entités de code de type valeur qui ne sont pas directement le type de la valeur d’une propriété, mais peuvent être évaluées à ce type. Cela est utile pour spécifier des valeurs qui existent déjà en tant que constantes connues dans une définition de type. Pour plus d’informations, consultez l'extension de balisage x:Static .

x :Null

x:Null spécifie null comme valeur pour un membre XAML. Selon la conception de types spécifiques ou de concepts de cadre plus larges, null n’est pas toujours une valeur par défaut pour une propriété, ou la valeur implicite d’un attribut de chaîne vide. Pour plus d'informations, consultez X:Null, extension de balisage.

x : Array

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 n’est délibérément pas utilisée. Pour plus d’informations, consultez extension de balisage x :Array. En XAML 2009 spécifiquement, les tableaux sont accessibles en tant que primitives de langage au lieu d’une extension. Pour plus d’informations, consultez caractéristiques du langage XAML 2009.

x :Référence

x:Reference fait partie de XAML 2009, une extension du jeu de langages d’origine (2006). x:Reference représente une référence à un autre objet existant dans un graphique d’objet. Cet objet est identifié par son x:Name. Pour plus d’informations, consultez l’extension de balisage x:Reference.

Autres x : Constructions

D’autres constructions x: pour prendre en charge les fonctionnalités de langage XAML existent, mais elles ne sont pas implémentées en tant qu’extensions de balisage. Pour plus d'informations, consultez les fonctionnalités de langage de l'espace de noms XAML (x:) .

Classe de base MarkupExtension

Pour définir une extension de balisage personnalisée qui peut interagir avec les implémentations par défaut des lecteurs XAML et des enregistreurs XAML dans System.Xaml, vous dérivez une classe de la classe abstraite MarkupExtension. Cette classe a une méthode à substituer, qui est ProvideValue. Vous devrez peut-être également définir des constructeurs supplémentaires pour prendre en charge les arguments de l’utilisation de l’extension de balisage et les propriétés modifiables correspondantes.

Par le biais de ProvideValue, une extension de balisage personnalisée a accès à un contexte de service qui signale l’environnement où l’extension de balisage est appelée par un processeur XAML. Dans le chemin de chargement, c'est généralement un XamlObjectWriter. Dans le chemin d’enregistrement, il s’agit généralement d’un XamlXmlWriter. Chaque rapport présente le contexte du service en tant que classe de contexte interne de fournisseur de services XAML, qui implémente un modèle de fournisseur de services. Pour plus d’informations sur les services disponibles et ce qu’ils représentent, consultez Convertisseurs de types et extensions de balisage pour XAML.

Votre classe d’extension de balisage doit utiliser un niveau d’accès public ; Les processeurs XAML doivent toujours être en mesure d’instancier la classe de prise en charge de l’extension de balisage afin d’utiliser ses services.

Définition du type de prise en charge d’une extension de balisage personnalisée

Lorsque vous utilisez des services XAML .NET ou des frameworks qui s’appuient sur les services XAML .NET, vous avez deux choix pour nommer le type de prise en charge de l’extension de balisage. Le nom du type est pertinent pour la façon dont les écrivains d’objets XAML tentent d’accéder et d’appeler un type de service d’extension de balisage lorsqu’ils rencontrent une utilisation de l’extension de balisage en XAML. Utilisez l’une des stratégies d’affectation de noms suivantes :

  • Nommez le nom du type pour qu’il corresponde exactement au jeton d’utilisation du balisage XAML. Par exemple, pour prendre en charge une utilisation de l’extension {Collate ...}, nommez le type de support Collate.
  • Nommez le nom de type pour être le jeton de chaîne d’utilisation ainsi que le suffixe Extension. Par exemple, pour prendre en charge une utilisation de l’extension {Collate ...}, nommez le type de support CollateExtension.

L'ordre de recherche consiste à rechercher d'abord le nom de la classe avec le suffixe Extension, puis à rechercher le nom de la classe sans le suffixe Extension.

Du point de vue de l'utilisation du balisage, l'inclusion du suffixe Extension dans cette utilisation est valable. Toutefois, cela se comporte comme si Extension fait vraiment partie du nom de classe, et les enregistreurs d’objets XAML ne parviennent pas à résoudre une classe de prise en charge de l’extension de balisage pour cette utilisation si la classe de support n’a pas le suffixe Extension.

Constructeur sans paramètre

Pour tous les types de prise en charge de l’extension de balisage, vous devez exposer un constructeur public sans paramètre. Un constructeur sans paramètre est requis pour tout cas où un enregistreur d’objets XAML instancie l’extension de balisage à partir d’une utilisation d’un élément objet. La prise en charge de l’utilisation des éléments d’objet est une attente équitable pour une extension de balisage, en particulier pour la sérialisation. Toutefois, vous pouvez implémenter une extension de balisage sans constructeur public si vous envisagez uniquement de prendre en charge les utilisations d’attributs de l’extension de balisage.

Si l’utilisation de votre extension de balisage n’a aucun argument, le constructeur sans paramètre est requis pour prendre en charge l’utilisation.

Modèles de constructeur et arguments positionnels pour une extension de balisage personnalisée

Pour une extension de balisage utilisant des arguments prévus, les constructeurs publics doivent correspondre aux modes d'utilisation prévus. En d’autres termes, si votre extension de balisage est conçue pour exiger un argument positionnel comme utilisation valide, vous devez prendre en charge un constructeur public avec un paramètre d’entrée qui prend l’argument positionnel.

Par exemple, supposons que l’extension de balisage Collate est destinée à prendre en charge uniquement un mode où il existe un argument positionnel qui représente son mode, spécifié en tant que constante d’énumération CollationMode. Dans ce cas, il doit y avoir un constructeur avec le formulaire suivant :

public Collate(CollationMode collationMode) {...}

Au niveau de base, les arguments passés à une extension de balisage sont une chaîne, car ils sont transférés à partir des valeurs d’attribut du balisage. Vous pouvez convertir tous vos arguments en chaînes de caractères et travailler avec les entrées à ce niveau. Toutefois, vous avez accès à certains traitements qui se produisent avant que les arguments d’extension de balisage ne soient passés à la classe de support.

Le traitement fonctionne conceptuellement comme si l’extension de balisage est un objet à créer, puis ses valeurs membres sont définies. Chaque propriété spécifiée à définir est évaluée de façon similaire à la façon dont un membre spécifié peut être défini sur un objet créé lorsque XAML est analysé. Il existe deux différences importantes :

  • Comme indiqué précédemment, un type de prise en charge de l’extension de balisage n’a pas besoin d’avoir un constructeur sans paramètres pour être instancié en XAML. Sa construction d’objet est différée jusqu’à ce que ses arguments possibles dans la syntaxe de texte soient tokenisés et évalués comme arguments positionnels ou nommés, et le constructeur approprié est appelé à ce moment-là.
  • Les utilisations des extensions de balisage peuvent être imbriquées. L’extension de balisage la plus interne est évaluée en premier. Par conséquent, vous pouvez supposer une telle utilisation et déclarer l’un des paramètres de construction comme un type devant utiliser un convertisseur de valeur (tel qu'une extension de balisage) pour produire.

Une dépendance à ce traitement a été illustrée dans l’exemple précédent. L’enregistreur d’objets XAML des services XAML .NET traite les noms de constantes d’énumération en valeurs énumérées au niveau natif.

Le traitement de la syntaxe de texte d’un paramètre positionnel d’extension de balisage peut également s’appuyer sur un convertisseur de type associé au type qui se trouve dans l’argument de construction.

Les arguments sont appelés arguments positionnels, car l’ordre dans lequel les jetons de l’utilisation sont rencontrés correspond à l’ordre positionnel du paramètre de constructeur auquel ils sont attribués. Par exemple, considérez la signature de constructeur suivante :

public Collate(CollationMode collationMode, object collateThis) {...}

Un processeur XAML attend deux arguments positionnels pour cette extension de balisage. S'il y a une utilisation de {Collate AlphaUp,{x:Reference circularFile}}, le jeton AlphaUp est envoyé au premier paramètre et évalué en tant que constante nommée CollationMode. Le résultat du x:Reference interne est envoyé au deuxième paramètre et évalué en tant qu’objet.

Dans les règles spécifiées par XAML pour la syntaxe et le traitement de l’extension de balisage, la virgule est le délimiteur entre les arguments, que ces arguments soient des arguments positionnels ou des arguments nommés.

Arité dupliquée des arguments positionnels

Si un auteur d’objets XAML rencontre une utilisation d’une extension de balisage avec des arguments positionnels, et qu’il existe plusieurs arguments de constructeur qui acceptent ce nombre d’arguments (une arité identique), ce n’est pas nécessairement une erreur. Le comportement dépend d’un paramètre de contexte de schéma XAML personnalisable, SupportMarkupExtensionsWithDuplicateArity. Si SupportMarkupExtensionsWithDuplicateArity est true, un générateur d’objets XAML ne doit pas lever d'exception uniquement en raison d'une arité dupliquée. Le comportement au-delà de ce point n’est pas strictement défini. L’hypothèse de conception de base est que le contexte de schéma contient des informations de type disponibles sur les paramètres spécifiques et peut tenter des casts explicites qui correspondent aux candidats doublons pour voir quelle signature est la meilleure correspondance. Une exception peut toujours être levée si aucune signature ne peut passer les tests imposés par ce contexte de schéma particulier qui s’exécute sur un enregistreur d’objets XAML.

Par défaut, SupportMarkupExtensionsWithDuplicateArity est false dans le CLR basé sur XamlSchemaContext pour les services XAML .NET. Ainsi, XamlObjectWriter par défaut lève des exceptions si elle rencontre une utilisation de l’extension de balisage où il existe une arité redondante dans les constructeurs du type sous-jacent.

Arguments nommés pour une extension de balisage personnalisée

Les extensions de balisage spécifiées par XAML peuvent également utiliser un formulaire d’arguments nommés pour l’utilisation. Au premier niveau de la tokenisation, la syntaxe du texte est divisée en arguments. La présence d’un signe égal (=) dans n’importe quel argument identifie un argument comme argument nommé. Un tel argument est également tokenisé dans une paire nom/valeur. Dans ce cas, le nom désigne une propriété modifiable publique du type d'assistance de l'extension de balisage. Si vous envisagez de prendre en charge l’utilisation des arguments nommés, vous devez fournir ces propriétés modifiables publiques. Les propriétés peuvent être héritées tant qu’elles restent publiques.

Accès au contexte du fournisseur de services à partir d’une implémentation d’extension de balisage

Les services disponibles sont les mêmes pour n’importe quel convertisseur de valeur. La différence réside dans la façon dont chaque convertisseur de valeurs reçoit le contexte de service. Accéder aux services et les services disponibles sont documentés dans la rubrique Convertisseurs de types et extensions de balisage pour XAML.

Utilisation des éléments de propriété d’une extension de balisage

Les scénarios d’utilisation des extensions de balisage sont souvent conçus autour de l’utilisation de l’extension de balisage dans l’utilisation des attributs. Il est toutefois potentiellement possible de définir la classe de support pour faciliter l'utilisation des éléments de propriété.

Pour prendre en charge l’utilisation des éléments de propriété de votre extension de balisage, définissez un constructeur sans paramètre public. Il doit s’agir d’un constructeur d’instance et non d’un constructeur statique. Cela est nécessaire, car un processeur XAML doit généralement appeler le constructeur sans paramètre sur tout élément objet qu’il traite à partir du balisage, et cela inclut les classes d’extension de balisage en tant qu’éléments d’objet. Pour les scénarios avancés, vous pouvez définir des chemins de construction non par défaut pour les classes. (Pour plus d’informations, consultez directive x :FactoryMethod.) Toutefois, vous ne devez pas utiliser ces modèles à des fins d’extension de balisage, car cela rend la découverte du modèle d’utilisation beaucoup plus difficile, à la fois pour les concepteurs et pour les utilisateurs de balisage brut.

Attribution pour une extension de balisage personnalisée

Pour prendre en charge les environnements de développement et certains scénarios d’écriture d’objets XAML, vous devez associer un type d'extension de balisage avec plusieurs attributs CLR. Ces attributs signalent l’utilisation prévue de l’extension de balisage.

MarkupExtensionReturnTypeAttribute rapporte les informations de Type pour le type d'objet que ProvideValue retourne. Par sa signature pure, ProvideValue renvoie Object. Mais différents consommateurs peuvent souhaiter des informations de type de retour plus précises. Cela inclut les éléments suivants :

  • Concepteurs et IDE, qui peuvent fournir une prise en charge sensible aux types pour les utilisations d’extension de balisage.
  • Implémentations avancées de gestionnaires SetMarkupExtension dans les classes cibles, qui peuvent utiliser la réflexion pour déterminer le type de retour d'une extension de balisage plutôt que de s'appuyer sur des implémentations connues sous le nom de MarkupExtension.

Sérialisation des utilisations d’extension de balisage

Lorsqu’un enregistreur d’objets XAML traite une utilisation de l’extension de balisage et appelle ProvideValue, le contexte dans lequel elle était précédemment utilisée comme extension de balisage subsiste dans le flux de nœuds XAML, mais pas dans le graphique d’objets. Dans le graphique d’objets, seule la valeur est conservée. Si vous avez des scénarios de conception ou d’autres raisons pour conserver l’utilisation de l’extension de balisage d’origine dans la sortie sérialisée, vous devez concevoir votre propre infrastructure pour suivre les utilisations de l’extension de balisage à partir du flux de nœud XAML du chemin de charge. Vous pouvez implémenter un comportement permettant de recréer les éléments du flux de nœud à partir du chemin de chargement et les transmettre aux enregistreurs XAML pour la sérialisation dans le chemin de sauvegarde, en remplaçant la valeur à la position appropriée dans le flux de nœud.

Extensions de balisage dans le flux de nœuds XAML

Si vous travaillez avec un flux de nœud XAML sur le chemin de chargement, l'utilisation d'une extension de balisage apparaît dans le flux de nœud en tant qu'objet.

Si l’utilisation de l’extension de balisage utilise des arguments positionnels, elle est représentée en tant qu’objet de début avec une valeur d’initialisation. En tant que représentation textuelle approximative, le flux de nœud ressemble à ce qui suit :

StartObject (XamlType est le type de définition de l’extension de balisage, et non son type de retour)

StartMember (nom du XamlMember est _InitializationText)

Value (la valeur est les arguments positionnels sous forme de chaîne, y compris les délimiteurs intermédiaires)

EndMember

EndObject

Une utilisation de l'extension de balisage avec des arguments nommés est représentée sous forme d'objet avec des membres portant les noms pertinents, chacun étant assigné des valeurs sous forme de chaînes de texte.

En fait, pour invoquer l’implémentation ProvideValue d’une extension de balisage, le contexte de schéma XAML est nécessaire, car cela requiert un mappage de type et la création d’une instance de type support pour extension de balisage. C’est une raison pour laquelle les utilisations de l’extension de balisage sont conservées de cette façon dans les flux de nœuds de services XAML .NET par défaut. La partie lecteur d’un chemin de chargement n’a souvent pas le contexte de schéma XAML nécessaire disponible.

Si vous utilisez un flux de nœuds XAML lors du parcours d'enregistrement, il n’existe généralement rien dans une représentation graphique d'un objet qui peut vous indiquer que l’objet à sérialiser a été initialement fourni par l'utilisation d'une extension de balisage et un résultat ProvideValue. Les scénarios qui doivent conserver les utilisations d’extension de balisage pour l’aller-retour tout en capturant d’autres modifications dans le graphique d’objet doivent concevoir leurs propres techniques pour préserver les connaissances d’une utilisation d’extension de balisage à partir de l’entrée XAML d’origine. Par exemple, pour restaurer les utilisations de l’extension de balisage, il peut être nécessaire de travailler avec le flux de nœuds sur le chemin d’enregistrement ou d'effectuer une fusion entre le XAML d’origine et le XAML aller-retour. Certaines infrastructures d’implémentation XAML telles que WPF utilisent des types intermédiaires (expressions) pour représenter les cas où les utilisations d’extension de balisage ont fourni les valeurs.

Voir aussi