Étendues de noms XAML WPF
Les étendues de nom XAML correspondent à un concept qui identifie des objets définis dans XAML. Les noms d’un namescope XAML peuvent être utilisés pour établir des relations entre les noms définis par XAML des objets et leurs équivalents d’instance dans une arborescence d’objets. En règle générale, les portées de noms XAML dans le code managé WPF sont créées lors du chargement des racines de page XAML individuelles pour une application XAML. Les portées de noms XAML en tant qu’objet de programmation sont définies par l’interface INameScope et sont également implémentées par la classe pratique NameScope.
Étendues de nom dans les applications XAML chargées
Dans un contexte de programmation ou d’informatique plus large, les concepts de programmation incluent souvent le principe d’un identificateur ou d’un nom unique qui peut être utilisé pour accéder à un objet. Pour les systèmes qui utilisent des identificateurs ou des noms, le namescope définit les limites dans lesquelles un processus ou une technique recherche si un objet de ce nom est demandé, ou les limites où l’unicité des noms d’identification est appliquée. Ces principes généraux sont vrais pour les namescopes XAML. Dans WPF, les portées de noms XAML sont créées sur l’élément racine d’une page XAML lorsque la page est chargée. Chaque nom spécifié dans la page XAML commençant à la racine de la page est ajouté à un namescope XAML pertinent.
Dans LE code XAML WPF, les éléments qui sont des éléments racines courants (tels que Pageet Window) contrôlent toujours un namescope XAML. Si un élément tel que FrameworkElement ou FrameworkContentElement est l’élément racine de la page dans le balisage, un processeur XAML ajoute implicitement une racine Page afin que le Page puisse fournir un namescope XAML de travail.
Note
Les actions de génération WPF créent un namescope XAML pour une production XAML, même si aucun attribut Name
ou x:Name
n’est défini sur tous les éléments du balisage XAML.
Si vous essayez d’utiliser le même nom deux fois dans un namescope XAML, une exception est levée. Pour le XAML WPF avec code-behind et faisant partie d'une application compilée, l'exception est levée au moment de la compilation par les actions de construction de WPF, lors de la création de la classe générée pour la page pendant la compilation initiale du balisage. Pour le code XAML qui n’est pas compilé par une action de génération, des exceptions liées aux problèmes de portée de noms XAML peuvent être déclenchées lorsque le code XAML est chargé. Les concepteurs XAML peuvent également anticiper les problèmes d'espace de noms XAML pendant la conception.
Ajout d’objets à des arborescences d’objets runtime
Le moment où XAML est analysé représente le moment dans le temps où un namescope XAML WPF est créé et défini. Si vous ajoutez un objet à une arborescence d’objets à un moment donné après l’analyse du code XAML qui a produit cette arborescence, une valeur Name
ou x:Name
sur le nouvel objet ne met pas automatiquement à jour les informations dans un namescope XAML. Pour ajouter un nom pour un objet dans un namescope XAML WPF après le chargement du code XAML, vous devez appeler l’implémentation appropriée de RegisterName sur l’objet qui définit la portée de nom XAML, qui est généralement la racine de la page XAML. Si le nom n’est pas inscrit, l’objet ajouté ne peut pas être référencé par le biais de méthodes telles que FindName, et vous ne pouvez pas utiliser ce nom pour le ciblage d’animation.
Le scénario le plus courant pour les développeurs d’applications est que vous utiliserez RegisterName pour inscrire des noms dans le namescope XAML à la racine actuelle de la page. RegisterName fait partie d’un scénario important pour les storyboards qui ciblent des objets pour les animations. Pour plus d’informations, consultez Vue d’ensemble des storyboards.
Si vous appelez RegisterName sur un objet autre que l’objet qui définit le namescope XAML, le nom est toujours inscrit dans le namescope XAML dans lequel l’objet appelant est conservé, comme si vous aviez appelé RegisterName sur l’objet de définition de nom XAML.
Étendues de nom XAML dans du code
Vous pouvez créer, puis utiliser des portées de noms XAML dans le code. Les API et les concepts impliqués dans la création de namescope XAML sont identiques même pour une utilisation pure du code, car le processeur XAML pour WPF utilise ces API et concepts lorsqu’il traite XAML lui-même. Les concepts et l’API existent principalement dans le but de pouvoir rechercher des objets par nom dans une arborescence d’objets qui est généralement définie partiellement ou entièrement en XAML.
Pour les applications créées par programmation et non à partir du code XAML chargé, l’objet qui définit un namescope XAML doit implémenter INameScope, ou être une classe dérivée FrameworkElement ou FrameworkContentElement, afin de prendre en charge la création d’un namescope XAML sur ses instances.
En outre, pour tout élément qui n’est pas chargé et traité par un processeur XAML, le namescope XAML de l’objet n’est pas créé ou initialisé par défaut. Vous devez créer explicitement un namescope XAML pour tout objet dans lequel vous avez l’intention d’inscrire des noms par la suite. Pour créer un namescope XAML, vous appelez la méthode de SetNameScope statique. Spécifiez l’objet qui le possède en tant que paramètre dependencyObject
et un nouvel appel de constructeur NameScope comme paramètre value
.
Si l’objet fourni en tant que dependencyObject
pour SetNameScope n’est pas une implémentation INameScope, FrameworkElement ou FrameworkContentElement, effectuer un appel de RegisterName sur les éléments enfants n’aura aucun effet. Si vous ne parvenez pas à créer explicitement la nouvelle portée de noms XAML, alors les appels à RegisterName déclencheront une exception.
Pour obtenir un exemple d’utilisation des API de portée de noms XAML dans le code, consultez Définir une étendue de nom.
Étendues de nom XAML dans les styles et les modèles
Les styles et les modèles dans WPF permettent de réutiliser et de réappliquer du contenu de manière simple. Toutefois, les styles et les modèles peuvent également inclure des éléments avec des noms XAML définis au niveau du modèle. Ce même modèle peut être utilisé plusieurs fois dans une page. Pour cette raison, les styles et les modèles définissent leurs propres portées de noms XAML, indépendamment de l’emplacement dans une arborescence d’objets où le style ou le modèle est appliqué.
Prenons l’exemple suivant :
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
<Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Page.Resources>
<StackPanel>
<Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
<Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
</StackPanel>
</Page>
Ici, le même modèle est appliqué à deux boutons différents. Si les modèles n’avaient pas de portées de noms XAML discrètes, le nom TheBorder
utilisé dans le modèle entraînerait une collision de noms dans le namescope XAML. Chaque instanciation du modèle a son propre namescope XAML. Dans cet exemple, chaque nom XAML du modèle instancié contient exactement un nom.
Les styles définissent également leur propre portée de noms XAML, principalement afin que les parties des storyboards puissent avoir des noms particuliers attribués. Ces noms permettent de contrôler des comportements spécifiques qui cibleront les éléments de ce nom, même si le modèle a été redéfini dans le cadre de la personnalisation du contrôle.
En raison des portées de noms XAML distinctes, la recherche d’éléments nommés dans un modèle est plus difficile que la recherche d’un élément nommé non basé sur un modèle dans une page. Vous devez d’abord déterminer le modèle appliqué en obtenant la valeur de propriété Template du contrôle où le modèle est appliqué. Ensuite, vous appelez la version du modèle de FindName, en passant le contrôle où le modèle a été appliqué comme deuxième paramètre.
Si vous êtes un auteur de contrôle et que vous générez une convention où un élément nommé particulier dans un modèle appliqué est la cible d’un comportement défini par le contrôle lui-même, vous pouvez utiliser la méthode GetTemplateChild à partir de votre code d’implémentation de contrôle. La méthode GetTemplateChild est protégée. Seul l’auteur du contrôle y a accès.
Si vous travaillez à partir d’un modèle et que vous devez accéder à l’étendue de noms XAML où le modèle est appliqué, obtenez la valeur de TemplatedParent, puis appelez FindName là. Un exemple de travail dans le modèle serait si vous écrivez l’implémentation du gestionnaire d’événements où l’événement sera déclenché à partir d’un élément dans un modèle appliqué.
Étendues de nom XAML et API relatives aux noms
FrameworkElement a des méthodes FindName, RegisterName et UnregisterName. Si l’objet sur lequel vous appelez ces méthodes possède un namescope XAML, les méthodes appellent les méthodes du namescope XAML approprié. Sinon, l’élément parent est vérifié pour voir s’il possède un namescope XAML, et ce processus continue de se poursuivre de manière récursive jusqu’à ce qu’un namescope XAML soit trouvé (en raison du comportement du processeur XAML, il est garanti qu’il s’agit d’un namescope XAML à la racine). FrameworkContentElement a des comportements analogues, à l’exception qu’aucun FrameworkContentElement ne possède jamais un namescope XAML. Les méthodes existent sur FrameworkContentElement afin que les appels puissent être transférés à un élément parent FrameworkElement.
SetNameScope est utilisé pour mapper un nouveau namescope XAML à un objet existant. Vous pouvez appeler SetNameScope plusieurs fois pour réinitialiser ou effacer le namescope XAML, mais ce n’est pas une utilisation courante. En outre, GetNameScope n’est généralement pas utilisé dans le code.
Implémentations d’étendue de nom XAML
Les classes suivantes implémentent INameScope directement :
ResourceDictionary n’utilise pas de noms XAML ni de portées de noms ; il utilise plutôt des clés, car il s’agit d’une implémentation de dictionnaire. La seule raison pour laquelle ResourceDictionary implémente INameScope est de sorte qu’elle puisse lever des exceptions au code utilisateur qui permettent de clarifier la distinction entre un vrai namescope XAML et comment un ResourceDictionary gère les clés, et pour garantir que les namescopes XAML ne sont pas appliqués à un ResourceDictionary par des éléments parents.
FrameworkTemplate et Style implémenter INameScope via des définitions d’interface explicites. Les implémentations explicites permettent à ces portées de noms XAML de se comporter de manière conventionnelle lorsqu’elles sont accessibles via l’interface INameScope, c’est-à-dire la façon dont les portées de noms XAML sont communiquées par les processus internes WPF. Mais les définitions d’interface explicites ne font pas partie de la surface d’API conventionnelle de FrameworkTemplate et de Style, car vous devez rarement appeler les méthodes INameScope sur FrameworkTemplate et Style directement, et utiliser plutôt d’autres API telles que GetTemplateChild.
Les classes suivantes définissent leur propre portée de nom XAML, en utilisant la classe d’assistance System.Windows.NameScope et en se connectant à son implémentation de namescope XAML via la propriété jointe NameScope.NameScope :
Voir aussi
.NET Desktop feedback