Définir des types personnalisés à utiliser avec les services XAML .NET
Lorsque vous définissez des types personnalisés qui sont des objets métier ou des types qui n’ont pas de dépendance sur des frameworks spécifiques, certaines bonnes pratiques sont recommandées pour XAML que vous pouvez suivre. Si vous suivez ces pratiques, les services XAML .NET et ses lecteurs XAML et enregistreurs XAML peuvent découvrir les caractéristiques XAML de votre type et lui donner une représentation appropriée dans un flux de nœuds XAML à l’aide du système de type XAML. Cette rubrique décrit les meilleures pratiques pour les définitions de types, les définitions de membres et l’attribut CLR des types ou des membres.
Modèles de constructeur et définitions de type pour XAML
Pour être instancié en tant qu’élément objet en XAML, une classe personnalisée doit répondre aux exigences suivantes :
La classe personnalisée doit être publique et doit exposer un constructeur public sans paramètre. (Consultez la section suivante pour obtenir des notes concernant les structures.)
La classe personnalisée ne doit pas être une classe imbriquée. Le « point » supplémentaire dans le chemin de nom complet rend la division d’espace de noms de classes ambiguë et interfère avec d’autres fonctionnalités XAML telles que les propriétés jointes. Si un objet peut être instancié en tant qu’élément objet, l’objet créé peut remplir la forme d’élément de propriété de toutes les propriétés qui prennent l’objet comme type sous-jacent.
Vous pouvez toujours fournir des valeurs d’objet pour les types qui ne répondent pas à ces critères, si vous activez un convertisseur de valeurs. Pour plus d’informations, consultez Convertisseurs de types et extensions de balisage pour lesXAML.
Structures
Les structures peuvent toujours être construites en XAML, par définition CLR. Cela est dû au fait qu’un compilateur CLR crée implicitement un constructeur sans paramètre pour une structure. Ce constructeur initialise toutes les valeurs de propriété à leurs valeurs par défaut.
Dans certains cas, le comportement de construction par défaut d’une structure n’est pas souhaitable. Cela peut être dû au fait que la structure est destinée à remplir des valeurs et à fonctionner conceptuellement en tant qu’union. En tant qu’union, les valeurs contenues peuvent avoir des interprétations mutuellement exclusives et, par conséquent, aucune de ses propriétés n’est paramétrable. Un exemple de telle structure dans le vocabulaire WPF est GridLength. Ces structures doivent implémenter un convertisseur de type afin que les valeurs puissent être exprimées sous forme d’attribut, à l’aide de conventions de chaîne qui créent les différentes interprétations ou modes des valeurs de structure. La structure doit également exposer un comportement similaire pour la construction du code par le biais d’un constructeur sans paramètre.
Interfaces
Les interfaces peuvent être utilisées comme types sous-jacents de membres. Le système de type XAML vérifie la liste assignable et s’attend à ce que l’objet fourni comme valeur puisse être affecté à l’interface. Il n’existe aucun concept de la façon dont l’interface doit être présentée en tant que type XAML tant qu’un type assignable pertinent prend en charge les exigences de construction XAML.
Méthodes d’usine
Les méthodes de fabrique sont une fonctionnalité XAML 2009. Ils modifient le principe XAML que les objets doivent avoir des constructeurs sans paramètre. Les méthodes de fabrique ne sont pas documentées dans cet article. Consultez directive x :FactoryMethod.
Énumérations
Les énumérations ont un comportement de conversion de type natif XAML. Les noms de constantes d’énumération spécifiés en XAML sont résolus par rapport au type d’énumération sous-jacent et retournent la valeur d’énumération à un enregistreur d’objets XAML.
XAML prend en charge une utilisation de style indicateurs pour les énumérations avec FlagsAttribute appliquée. Pour plus d’informations, consultez syntaxe XAML en détail. (syntaxe XAML en détail est écrite pour l’audience WPF, mais la plupart des informations de cette rubrique sont pertinentes pour XAML qui n’est pas spécifique à un framework d’implémentation particulier.)
Définitions de membres
Les types peuvent définir des membres pour l’utilisation XAML. Il est possible que les types définissent des membres utilisables en XAML même si ce type spécifique n’est pas utilisable en XAML. Cela est possible en raison de l’héritage CLR. Tant que certains types qui héritent du membre prennent en charge l’utilisation XAML en tant que type, et que le membre prend en charge l’utilisation XAML pour son type sous-jacent ou a une syntaxe XAML native disponible, ce membre est utilisable en XAML.
Propriétés
Si vous définissez des propriétés en tant que propriété CLR publique à l’aide de la get
CLR standard et des modèles d’accesseur set
et des mots clés appropriés au langage, le système de type XAML peut signaler la propriété en tant que membre avec les informations appropriées fournies pour XamlMember propriétés, telles que IsReadPublic et IsWritePublic.
Des propriétés spécifiques peuvent activer une syntaxe de texte en appliquant TypeConverterAttribute. Pour plus d’informations, consultez Convertisseurs de types et extensions de balisage pour lesXAML.
En l’absence d’une syntaxe de texte ou d’une conversion XAML native et en l’absence d’une autre indirection, comme une utilisation de l’extension de balisage, le type d’une propriété (TargetType dans le système de type XAML) doit pouvoir retourner une instance à un enregistreur d’objets XAML en traitant le type cible comme un type CLR.
Si vous utilisez XAML 2009, extension de balisage x :Reference pouvez être utilisé pour fournir des valeurs si les considérations précédentes ne sont pas remplies ; toutefois, il s’agit davantage d’un problème d’utilisation qu’un problème de définition de type.
Épreuves
Si vous définissez des événements en tant qu’événement CLR public, le système de type XAML peut signaler l’événement en tant que membre avec IsEvent comme true
. Le câblage des gestionnaires d’événements n’est pas dans l’étendue des fonctionnalités des services XAML .NET ; le câblage est laissé à des infrastructures et des implémentations spécifiques.
Méthode
Le code inline pour les méthodes n’est pas une fonctionnalité XAML par défaut. Dans la plupart des cas, vous ne référencez pas directement les membres de méthode à partir de XAML, et le rôle des méthodes en XAML n’est que pour prendre en charge des modèles XAML spécifiques. directive x :FactoryMethod est une exception.
Champs
Les instructions de conception CLR découragent les champs non statiques. Pour les champs statiques, vous pouvez accéder aux valeurs de champs statiques uniquement via x :Static Markup Extension; dans ce cas, vous ne faites rien de spécial dans la définition CLR pour exposer un champ pour les utilisations x :Static.
Membres attachables
Les membres attachables sont exposés au code XAML via un modèle de méthode d’accesseur sur un type de définition. Le type de définition lui-même n’a pas besoin d’être utilisable en XAML en tant qu’objet. En fait, un modèle courant consiste à déclarer une classe de service dont le rôle est de posséder le membre attachable et d’implémenter les comportements associés, mais ne sert aucune autre fonction, comme une représentation de l’interface utilisateur. Pour les sections suivantes, l’espace réservé PropertyName représente le nom de votre membre pouvant être attaché. Ce nom doit être valide dans la grammaire XamlName.
Soyez prudent quant aux collisions de noms entre ces modèles et d’autres méthodes d’un type. Si un membre existe qui correspond à l’un des modèles, il peut être interprété comme un chemin d’utilisation de membre attachable par un processeur XAML, même si ce n’était pas votre intention.
Accesseur GetPropertyName
La signature de l’accesseur GetPropertyName
doit être :
public static object GetPropertyName(object target)
L’objet
target
peut être spécifié en tant que type plus spécifique dans votre implémentation. Vous pouvez l’utiliser pour étendre l’utilisation de votre membre pouvant être attaché ; les utilisations en dehors de votre étendue prévue lèvent des exceptions de cast non valides qui sont ensuite exposées par une erreur d’analyse XAML. Le nom du paramètretarget
n’est pas obligatoire, mais est nommétarget
par convention dans la plupart des implémentations.La valeur de retour peut être spécifiée en tant que type plus spécifique dans votre implémentation.
Pour prendre en charge une syntaxe de texte TypeConverter activée pour l’utilisation des attributs du membre pouvant être attaché, appliquez TypeConverterAttribute au accesseur GetPropertyName
. L’application à la get
au lieu du set
peut sembler non intuitive ; Toutefois, cette convention peut prendre en charge le concept de membres attachables en lecture seule qui sont sérialisables, ce qui est utile dans les scénarios de concepteur.
Accesseur SetPropertyName
La signature de l’accesseur SetPropertyName
doit être :
public static void SetPropertyName(object target, object value)
L’objet
target
peut être spécifié en tant que type plus spécifique dans votre implémentation, avec la même logique et les mêmes conséquences que celles décrites dans la section précédente.L’objet
value
peut être spécifié en tant que type plus spécifique dans votre implémentation.
N’oubliez pas que la valeur de cette méthode est l’entrée provenant de l’utilisation XAML, généralement sous forme d’attribut. À partir du formulaire d’attribut, il doit y avoir une prise en charge du convertisseur de valeur pour une syntaxe de texte et vous attribuez l’attribut sur l’accesseur GetPropertyName
.
Magasins de membres attachables
Les méthodes d’accesseur ne sont généralement pas suffisantes pour fournir un moyen de placer des valeurs membres attachables dans un graphique d’objet, ou de récupérer des valeurs hors du graphique d’objet et de les sérialiser correctement. Pour fournir cette fonctionnalité, les objets target
dans les signatures d’accesseur précédentes doivent être capables de stocker des valeurs. Le mécanisme de stockage doit être cohérent avec le principe de membre attachable que le membre est attaché à des cibles où le membre pouvant être attaché n’est pas dans la liste des membres. Les services XAML .NET fournissent une technique d’implémentation pour les magasins de membres attachables via les API IAttachedPropertyStore et AttachablePropertyServices.
IAttachedPropertyStore est utilisé par les enregistreurs XAML pour découvrir l’implémentation du magasin et doit être implémenté sur le type qui est la target
des accesseurs. Les API statiques AttachablePropertyServices sont utilisées dans le corps des accesseurs et font référence au membre attachable par son AttachableMemberIdentifier.
XAML-Related attributs CLR
L’attribution correcte de vos types, membres et assemblys est importante pour signaler les informations système de type XAML aux services XAML .NET. Les informations système de type XAML de création de rapports sont pertinentes si l’une des situations suivantes s’applique :
- Vous prévoyez que vos types soient utilisés avec des systèmes XAML qui sont directement basés sur les lecteurs XAML des services XAML .NET et les enregistreurs XAML.
- Vous définissez ou utilisez une infrastructure d’utilisation XAML basée sur ces lecteurs XAML et les enregistreurs XAML.
Pour obtenir la liste de chaque attribut lié au code XAML pertinent pour la prise en charge XAML de vos types personnalisés, consultez XAML-Related attributs CLR pour les types et bibliothèques personnalisés.
Usage
L’utilisation des types personnalisés nécessite que l’auteur du balisage mappe un préfixe pour l’assembly et l’espace de noms CLR qui contiennent le type personnalisé. Cette procédure n’est pas documentée dans cette rubrique.
Niveau d’accès
XAML fournit un moyen de charger et d’instancier des types qui ont un niveau d’accès internal
. Cette fonctionnalité est fournie afin que le code utilisateur puisse définir ses propres types, puis instancier ces classes à partir du balisage qui fait également partie de la même étendue de code utilisateur.
Un exemple de WPF est chaque fois que le code utilisateur définit un UserControl destiné à refactoriser un comportement d’interface utilisateur, mais pas dans le cadre d’un mécanisme d’extension possible qui peut être implicite en déclarant la classe de prise en charge avec public
niveau d’accès. Une telle UserControl peut être déclarée avec internal
accès si le code de stockage est compilé dans le même assembly à partir duquel il est référencé en tant que type XAML.
Pour une application qui charge xaml en confiance totale et utilise XamlObjectWriter, le chargement de classes avec internal
niveau d’accès est toujours activé.
Pour une application qui charge XAML en cas d’approbation partielle, vous pouvez contrôler les caractéristiques de niveau d’accès à l’aide de l’API XamlAccessLevel. En outre, les mécanismes de report (tels que le système de modèle WPF) doivent être en mesure de propager toutes les autorisations de niveau d’accès et de les conserver pour les évaluations de temps d’exécution éventuelles ; cela est géré en interne en transmettant les informations XamlAccessLevel.
Implémentation WPF
WPF XAML utilise un modèle d’accès à confiance partielle où si BAML est chargé sous approbation partielle, l’accès est limité à AssemblyAccessTo pour l’assembly qui est la source BAML. Pour le report, WPF utilise IXamlObjectWriterFactory.GetParentSettings comme mécanisme de transmission des informations de niveau d’accès.
Dans la terminologie XAML WPF, un type interne est un type défini par le même assembly qui inclut également le code XAML de référencement. Un tel type peut être mappé via un espace de noms XAML qui omet délibérément la partie assembly= d’un mappage, par exemple, xmlns:local="clr-namespace:WPFApplication1"
. Si BAML fait référence à un type interne et que ce type a internal
niveau d’accès, cela génère une classe GeneratedInternalTypeHelper
pour l’assembly. Si vous souhaitez éviter GeneratedInternalTypeHelper
, vous devez utiliser public
niveau d’accès, ou prendre en compte la classe pertinente dans un assembly distinct et rendre cet assembly dépendant.
Voir aussi
- XAML-Related attributs CLR pour les types et bibliothèques personnalisés
- des services XAML
.NET Desktop feedback