Portées de nom XAML WPF

Les portées de nom XAML correspondent à un concept qui identifie des 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 instances équivalentes 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 NameScopepratique.

Portées de nom dans les applications XAML chargées

Dans un contexte plus large de programmation ou d’informatique, 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, la portée de nom définit les limites à l’intérieur desquelles un processus ou une technique recherche si un objet de ce nom est demandé, ou les limites dans lesquelles l’unicité des noms qui identifient est appliquée. Ces principes généraux sont vrais pour les portées de nom XAML. Dans WPF, les portées de nom XAML sont créées sur l’élément racine d’une page XAML quand la page est chargée. Chaque nom spécifié dans la page XAML en commençant à la racine de la page est ajouté à une portée de nom XAML pertinente.

Dans WPF XAML, les éléments qui sont des éléments racines communs (tels que Page, et 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 Page racine afin que le Page fichier puisse fournir un namescope XAML fonctionnel.

Remarque

Les actions de génération WPF créent un namescope XAML pour une production XAML même si aucun ou x:Name attribut n’est Name défini sur les éléments 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 du XAML WPF qui a du code-behind et qui 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 initiale du balisage. Pour le XAML qui n’est 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 à des arborescences d’objets d’exécution

Le moment où le XAML est analysé correspond au moment une portée de nom XAML WPF est créée et définie. Si vous ajoutez un objet à une arborescence d’objets après l’analyse du code XAML ayant généré cette arborescence, une valeur Name ou x:Name sur le nouvel objet ne met pas automatiquement à jour les informations contenues dans une portée de nom 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 l’objet qui définit le namescope 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 nom 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 allez utiliser 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 les objets pour les animations. Pour plus d’informations, consultez Vue d’ensemble des plans conceptuels.

Si vous appelez RegisterName 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.

Portées de nom XAML dans du code

Vous pouvez créer et ensuite utiliser des portées de nom XAML dans du 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 pour pouvoir rechercher des objets par nom dans une arborescence d’objets définie partiellement ou entièrement en XAML.

Pour les applications créées par programme et non à partir du code XAML chargé, l’objet qui définit un namescope XAML doit implémenter INameScope, ou être une FrameworkElement classe dérivée, FrameworkContentElement afin de prendre en charge la création d’un namescope 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 prévoyez d’inscrire des noms par la suite. Pour créer un namescope XAML, vous appelez la méthode statique SetNameScope . Spécifiez l’objet qui le possède en tant que dependencyObject paramètre et un nouvel NameScope appel de constructeur comme value paramètre.

Si l’objet fourni comme dependencyObject pour SetNameScope n’est pas une INameScope implémentation, FrameworkElement ou FrameworkContentElementsi l’appel RegisterName sur des éléments enfants n’a aucun effet. Si vous ne parvenez pas à créer explicitement le nomscope XAML, les appels à RegisterName déclencheront une exception.

Pour obtenir un exemple d’utilisation des API de portée de nom XAML dans du code, consultez 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 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 d’un 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 l’emplacement où le style ou le modèle est appliqué dans une arborescence d’objets.

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 nom XAML discrètes, le nom TheBorder utilisé dans le modèle provoquerait un conflit de noms dans la portée de nom XAML. Chaque instanciation du modèle a sa propre portée de nom XAML. Ainsi, dans cet exemple, la portée de nom XAML de chaque modèle instancié contient un et un seul nom.

Les styles définissent également leur propre portée de nom XAML, principalement pour que des noms particuliers puissent être affectés aux différentes parties des plans conceptuels. Ces noms activent des comportements spécifiques des contrôles qui ciblent 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 nom XAML distinctes, rechercher des éléments nommés dans un modèle est plus difficile que rechercher dans une page un élément nommé non basé sur un modèle. Vous devez d’abord déterminer le modèle appliqué en obtenant la Template valeur de propriété 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é en tant que 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 GetTemplateChild méthode à partir de votre code d’implémentation de contrôle. La méthode est protégée. Seul GetTemplateChild 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 , TemplatedParentpuis appelez-y FindName . Un exemple de travail à l’intérieur du modèle est l’écriture de l’implémentation du gestionnaire d’événements là où l’événement est déclenché à partir d’un élément dans un modèle appliqué.

FrameworkElement a FindName, RegisterName et UnregisterName des méthodes. Si l’objet sur lequel vous appelez ces méthodes a une portée de nom XAML, les méthodes font les appels au sein des méthodes de la portée de nom XAML appropriée. Sinon, l’élément parent est vérifié pour voir s’il détient 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, à l’exception qu’il n’y FrameworkContentElement aura jamais de portée de nom XAML. Les méthodes existent pour FrameworkContentElement que les appels puissent être transférés éventuellement à un FrameworkElement élément parent.

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é à partir du code.

Implémentations de portée de nom XAML

Les classes suivantes implémentent INameScope directement :

ResourceDictionary n’utilise pas de noms XAML ou 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 les implémentations INameScope est de sorte qu’elle peut déclencher des exceptions au code utilisateur qui permettent de clarifier la distinction entre un vrai namescope XAML et comment un ResourceDictionary handles clés, et également pour garantir que les portées de noms XAML ne sont pas appliquées à un ResourceDictionary élément parent.

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 conventionnelle de l’API et FrameworkTemplateStyle, car vous devez rarement appeler les INameScope méthodes sur FrameworkTemplate et Style directement, et utiliser plutôt d’autres API telles que GetTemplateChild.

Les classes suivantes définissent leur propre namescope XAML, à l’aide de la System.Windows.NameScope classe d’assistance et en se connectant à son implémentation de namescope XAML via la NameScope.NameScope propriété jointe :

Voir aussi