Partager via


Portées de nom XAML WPF

Les portées de nom XAML sont un concept qui identifie les objets définis en XAML. Les noms dans une portée de nom XAML peuvent être utilisés pour établir des relations entre les noms définis en XAML des objets et leurs équivalents d'instances dans une arborescence d'objets. En général, les portées de nom XAML dans le code managé WPF sont créées lors du chargement des racines de la page XAML pour une application XAML. Les portées de nom 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.

Cette rubrique comprend les sections suivantes.

  • Les portées de noms dans les applications XAML chargées
  • Portées de nom XAML dans les styles et les modèles
  • Portées de nom XAML et API associées à des noms
  • Rubriques connexes

Les portées de noms dans les applications XAML chargées

Dans un contexte de programmation ou informatique plus général, les concepts de programmation incluent souvent le principe d'un identificateur ou nom unique qui peut être utilisé pour accéder à un objet. Pour les systèmes qui utilisent des identificateurs ou des noms de ce type, la portée de nom définit les limites indiquant à quel endroit un processus ou une technique effectuera des recherches si un objet de ce nom est demandé, ou les limites dans lesquelles le caractère unique des noms d'identification est appliqué. Ces principes généraux sont vrais pour des portées de nom XAML. Dans WPF, les portées de nom XAML sont créées sur l'élément racine d'une page XML lorsque la page est chargée. Chaque nom spécifié dans la page XAML en commençant à sa racine est ajouté à une portée de nom XAML pertinente.

Dans le XAML de WPF, les éléments qui sont des éléments racine courants (Page et Window, par exemple) contrôlent toujours une portée de nom 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 de sorte que la Page puisse fournir une portée de nom XAML qui fonctionne.

RemarqueRemarque

Les actions de génération WPF créent une portée de nom XAML pour la production XAML même si aucun attribut Name ou x:Name n'est défini sur un élément du balisage XAML.

Si vous essayez d'utiliser deux fois le même nom dans une portée de nom XAML, une exception est levée. Pour le XAML de WPF qui a du code-behind et fait partie d'une application compilée, l'exception est levée au moment de la génération par les actions de génération WPF, lors de la création de la classe générée pour la page pendant la compilation de balisage initiale. Pour le XAML non compilé par balisage par aucune action de génération, des exceptions liées aux problèmes de portée de nom XAML peuvent être déclenchées lors du chargement du XAML. Les concepteurs XAML peuvent également anticiper les problèmes de portée de nom XAML au moment du design.

Ajout d'objets aux arborescences d'objet d'exécution

Le moment où le langage XAML est analysé représente celui où une portée de nom XAML WPF est créée et définie. Si vous ajoutez un objet à une arborescence d'objets à tout moment après que le code XAML ayant généré cette arborescence a été analysé, une valeur Name ou x:Name sur le nouvel objet ne met pas automatiquement à jour les informations dans une portée de nom XAML. Pour ajouter un nom à un objet dans une portée de nom XAML WPF après le chargement de 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 en général la racine de la page XAML. Si le nom n'est pas enregistré, l'objet ajouté ne peut pas être référencé par son nom via des méthodes comme 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 consiste à utiliser RegisterName pour enregistrer les noms dans la portée de nom XAML sur la racine actuelle de la page. RegisterName fait partie d'un scénario important pour les tables de montage séquentiel 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 la portée de nom XAML, le nom est toujours enregistré dans la portée de nom XAML dans lequel l'objet appelant est conservé, comme si vous aviez appelé RegisterName sur la portée de nom XAML définissant l'objet.

Portées de nom XAML dans le code

Vous pouvez créer puis utiliser des portées de nom XAML dans le code. Les API et les concepts impliqués dans la création de la portée de nom XAML sont les mêmes, même pour une utilisation de code pur, car le processeur XAML pour WPF utilise ces API et concepts lorsqu'il traite le XAML lui-même. Les concepts et l'API existent principalement pour pouvoir rechercher des objets par leur nom dans une arborescence d'objets généralement définie complètement ou partiellement en XAML.

Pour les applications créées par programmation, et pas depuis un XAML chargé, l'objet qui définit une portée de nom XAML doit implémenter INameScope ou être une classe dérivée de FrameworkElement ou FrameworkContentElement afin de prendre en charge la création d'une portée de nom XAML sur ses instances.

De même, pour tout élément qui n'est pas chargé et traité par un processeur XAML, la portée de nom XAML pour l'objet n'est pas créée ou initialisée par défaut. Vous devez créer explicitement une nouvelle portée de nom XAML pour tout objet dans lequel vous envisagez d'enregistrer des noms par la suite. Pour créer une portée de nom XAML, vous appelez la méthode SetNameScope statique. Spécifiez l'objet qui le possédera en tant que paramètre dependencyObject, ainsi qu'un nouvel appel de constructeur NameScope en tant que paramètre value.

Si l'objet fourni comme dependencyObject pour SetNameScope n'est pas une implémentation INameScope, FrameworkElement ou FrameworkContentElement, appelant RegisterName sur tout élément enfant n'aura aucun effet. Si vous ne parvenez pas à créer la nouvelle portée de nom XAML explicitement, les appels à RegisterName lèveront une exception.

Pour obtenir un exemple de l'utilisation des API de portée de nom XAML dans du code, consultez Comment : définir une portée de nom.

Portées de nom XAML dans les styles et les modèles

Les styles et les modèles de WPF offrent la possibilité de réutiliser et de réappliquer le contenu d'une façon simple. Toutefois, les styles et les modèles peuvent également comprendre des éléments avec des noms XAML définis au niveau de 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 tous deux leurs propres portées de nom XAML, indépendamment de toute emplacement dans une arborescence d'objets où le style ou le modèle est appliqué.

Prenons l'exemple suivant :

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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 nom XAML discrètes, le nom TheBorder utilisé dans le modèle provoquerait un conflit de nom dans la portée de nom XAML. Chaque instanciation du modèle a sa propre portée de nom XAML ; c'est pourquoi, dans cet exemple, la portée de nom XAML de chaque modèle instancié contient exactement un nom.

Les styles définissent également leur propre portée de nom XAML, essentiellement afin que les différentes parties des storyboards puissent avoir des noms particuliers. Ces noms activent des comportements spécifiques des contrôles qui cibleront des éléments de ce nom, même si le modèle a été redéfini dans le cadre de la personnalisation de contrôle.

En raison de la séparation des portées de nom XAML, 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 tout 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é. Vous appelez ensuite la version de modèle de FindName, en passant le contrôle où le modèle a été appliqué comme deuxième paramètre.

Si vous êtes 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 pour un comportement défini par le contrôle lui-même, vous pouvez utiliser la méthode GetTemplateChild de votre code d'implémentation de contrôle. La méthode GetTemplateChild est protégée, de sorte que seul l'auteur du contrôle y a accès.

Si vous travaillez à partir d'un modèle et que vous devez récupérer la portée de nom XAML à laquelle le modèle est appliqué, récupérez la valeur de TemplatedParent, puis appelez FindName. 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é.

Portées de nom XAML et API associées à des noms

FrameworkElement a FindName, RegisterName et les méthodes UnregisterName. Si l'objet sur lequel vous appelez ces méthodes possède une portée de nom XAML, les méthodes appellent les méthodes de la portée de nom XAML pertinente. Sinon, l'élément parent est vérifié pour voir s'il possède une portée de nom XAML, et ce processus continue de manière récursive jusqu'à ce qu'une portée de nom XAML soit trouvée (en raison du comportement du processeur XAML, la présence d'une portée de nom XAML à la racine est garantie). FrameworkContentElement a des comportements analogues, à ceci près qu'aucun FrameworkContentElement ne possédera jamais une portée de nom XAML. Les méthodes existent sur FrameworkContentElement afin que les appels puissent être envoyés par la suite à un élément parent FrameworkElement.

SetNameScope est utilisé pour mapper une nouvelle portée de nom XAML à un objet existant. Vous pouvez appeler SetNameScope plusieurs fois pour réinitialiser ou effacer la portée de nom XAML, mais il ne s'agit pas d'une pratique courante. De même, GetNameScope n'est pas généralement utilisé à partir du code.

Implémentations de portées de nom XAML

Les classes suivantes implémentent INameScope directement :

ResourceDictionary n'utilise pas de noms ou de portées de nom XAML ; il utilise à la place des clés, parce qu'il s'agit d'une implémentation de dictionnaire. La seule raison pour laquelle ResourceDictionary implémente INameScope est que cela lui permet de lever des exceptions au code utilisateur qui aident à clarifier la distinction entre une véritable portée de nom XAML et la manière dont un ResourceDictionary gère les clés, et également pour de s'assurer que les portées de nom XAML ne sont pas appliquées à un ResourceDictionary par des éléments parents.

FrameworkTemplate et Style implémentent INameScope via des définitions d'interface explicites. Les implémentations explicites permettent à ces portées de nom XAML de se comporter de manière conventionnelle lorsqu'on y accède via l'interface INameScope (ce qui constitue la manière dont les portées de nom XAML sont communiquées par les processus internes WPF). En revanche, les définitions d'interface explicites ne font pas partie de la partie API classique de FrameworkTemplate et Style, étant donné que vous ne devez que rarement appeler directement les méthodes INameScope sur FrameworkTemplate et Style, et devez à la place utiliser une autre API telle que GetTemplateChild.

Les classes suivantes définissent leurs propres portées de nom XAML en utilisant la classe d'assistance System.Windows.NameScope et en se connectant à son implémentation de portée de nom XAML par le biais de la propriété jointe NameScope.NameScope :

Voir aussi

Référence

x:Name, directive

Concepts

Espaces de noms XAML et mappage d'espace de noms pour XAML WPF