Dans WPF, quelles sont les différences entre les attributs x: Name et Name?

574

Le titre dit tout. Parfois, il semble que les attributs Nameet x:Namesoient interchangeables.

Alors, quelles sont les différences définitives entre eux, et quand est-il préférable d'utiliser l'un sur l'autre?

Y a-t-il des implications en termes de performances ou de mémoire dans leur mauvaise utilisation?

Drew Noakes
la source
Les réponses suggèrent que l'utilisation de x:Nametout le temps fonctionne bien. Je viens de devoir le changer Namesinon je ne pourrais pas référencer le contrôle dans mon code .xaml.cs donc je vais supposer que ce n'est plus le cas qu'il fonctionne bien tout le temps.
Ortund
1
En ce qui concerne votre retour en arrière, quel sens supplémentaire est donné par l'expression "le titre dit tout", Drew? N'est-ce pas redondant? (Ma raison pour l'édition est que j'ai tendance à décourager les phrases de remplissage conversationnelles - ce n'est pas plus informatif que "je me demande si vous pouvez m'aider").
halfer

Réponses:

481

Il n'y a vraiment qu'un seul nom en XAML, le x:Name. Un framework, tel que WPF, peut éventuellement mapper l'une de ses propriétés aux XAML x:Nameen utilisant RuntimeNamePropertyAttributela classe sur qui désigne l'une des propriétés des classes comme mappant à l'attribut x: Name de XAML.

La raison pour laquelle cela a été fait était de permettre des frameworks qui ont déjà un concept de "Nom" au moment de l'exécution, comme WPF. Dans WPF, par exemple, FrameworkElementintroduit une propriété Name.

En général, une classe n'a pas besoin de stocker le nom pour x:Nameêtre utilisable. Tout x:Namemoyen pour XAML est de générer un champ pour stocker la valeur dans le code derrière la classe. Ce que le runtime fait avec ce mappage dépend du framework.

Alors, pourquoi y a-t-il deux façons de faire la même chose? La réponse simple est qu'il existe deux concepts mappés sur une propriété. WPF veut que le nom d'un élément soit conservé au moment de l'exécution (qui est utilisable entre autres par Bind) et XAML doit savoir quels éléments vous voulez être accessibles par les champs dans le code derrière la classe. WPF relie ces deux éléments en marquant la propriété Name comme un alias de x: Name.

À l'avenir, XAML aura plus d'utilisations pour x: Name, comme vous permettant de définir des propriétés en faisant référence à d'autres objets par leur nom, mais dans les versions 3.5 et antérieures, il n'est utilisé que pour créer des champs.

Que vous deviez utiliser l'un ou l'autre est vraiment une question de style, pas une question technique. Je laisserai cela à d'autres pour une recommandation.

Voir aussi AutomationProperties.Name VS x: Name , AutomationProperties.Name est utilisé par les outils d'accessibilité et certains outils de test.

chuckj
la source
2
Dans Visual Studio 2010, la propriété Name est définie (pas x: Name) lorsque vous modifiez le XAML via le concepteur. Il semble que MS encourage l'utilisation de Name sur x: Name, donc je suppose que c'est la norme de facto.
Nebula
11
Je ne pense pas que les deux soient interchangeables en général. La dénomination des contrôles utilisateur nécessite, x:Namecar Namene créerait pas de champ à reconnaître en code-behind. Je ne sais toujours pas pourquoi cela se produit, cependant.
Libor
5
Ils ne le sont pas et je ne voulais pas laisser entendre qu'ils l'ont fait. Dans WPF, si un élément a une Namepropriété, cela signifie la même chose. Si l'élément n'a pas de Namepropriété, vous devez utiliser x:Name.
chuckj
90

Ce n'est pas la même chose.

x:Nameest un concept xaml, utilisé principalement pour référencer des éléments. Lorsque vous attribuez à un élément l'attribut x: Name xaml, "le spécifié x:Namedevient le nom d'un champ qui est créé dans le code sous-jacent lorsque xaml est traité, et ce champ contient une référence à l'objet". ( MSDN ) Il s'agit donc d'un champ généré par le concepteur, qui a un accès interne par défaut.

Nameest la propriété de chaîne existante de a FrameworkElement, répertoriée comme toute autre propriété d'élément wpf sous la forme d'un attribut xaml.

En conséquence, cela signifie également qu'il x:Namepeut être utilisé sur une plus large gamme d'objets. Il s'agit d'une technique pour permettre à tout élément de xaml d'être référencé par un nom donné.

Kenan EK
la source
6
Alors pourquoi utiliser Name ou x: Name avec Binding.ElementName? Il semble que l'attribut x: Name soit non seulement utilisé pour nommer un champ dans le code généré, mais qu'il est également disponible dans les métadonnées au moment de l'exécution.
Drew Noakes
Il s'agit d'un champ généré comme le champ Nom dans les propriétés de conception de l'éditeur WinForms. Là, vous placez un nom dans la liste des propriétés et il devient le nom d'un champ. C'est le même comportement. Bien sûr, il est disponible au moment de l'exécution car il s'agit d'un champ interne compilé dans le code derrière. Binding.ElementName vérifie les deux cas, c'est-à-dire l'éditeur xaml "magic", le x: Name n'est pas magique en soi.
Kenan EK
39

x: Nom et Nom font référence à des espaces de noms différents.

x: nom est une référence à l'espace de noms x défini par défaut en haut du fichier Xaml.

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Dire simplement que Name utilise l'espace de noms par défaut ci-dessous.

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

x: Nom signifie utiliser l'espace de noms qui a le x alias . x est la valeur par défaut et la plupart des gens la quittent, mais vous pouvez la changer en ce que vous voulez

xmlns:foo="http://schemas.microsoft.com/winfx/2006/xaml"

donc votre référence serait foo: nom

Définir et utiliser des espaces de noms dans WPF


OK, regardons cela différemment. Supposons que vous glissiez et déposiez un bouton sur votre page Xaml. Vous pouvez référencer ce 2 façons x: nom et nom . Tous les xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" et xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml" sont des références à plusieurs espaces de noms . Étant donné que xaml contient l' espace de noms Control (pas 100% sur cela) et la présentation contient FrameworkElement ET la classe Button a un modèle d'héritage de:

Button : ButtonBase
ButtonBase : ContentControl, ICommandSource
ContentControl : Control, IAddChild
Control : FrameworkElement
FrameworkElement : UIElement, IFrameworkInputElement, 
                    IInputElement, ISupportInitialize, IHaveResources

Donc, comme on pourrait s'y attendre, tout ce qui hérite de FrameworkElement aurait accès à tous ses attributs publics. ainsi, dans le cas de Button, il obtient son attribut Name de FrameworkElement, tout en haut de l'arborescence de la hiérarchie. Ainsi , vous pouvez dire x: Nom ou nom et ils seront à la fois être l' accès au getter / setter de la FrameworkElement.

Référence MSDN

WPF définit un attribut CLR utilisé par les processeurs XAML afin de mapper plusieurs espaces de noms CLR à un seul espace de noms XML. L' attribut XmlnsDefinitionAttribute est placé au niveau de l'assembly dans le code source qui produit l'assembly. Le code source de l'assembly WPF utilise cet attribut pour mapper les divers espaces de noms courants, tels que System.Windows et System.Windows.Controls, à la espace de noms http://schemas.microsoft.com/winfx/2006/xaml/presentation .

Ainsi, les attributs d'assemblage ressembleront à:

PresentationFramework.dll - XmlnsDefinitionAttribute:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Data")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Navigation")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Documents")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls")]  
cgreeno
la source
1
Je ne pense pas qu'il est vrai que http://schemas.microsoft.com/winfx/2006/xamldétient Controlpuisque vous pouvez l' utiliser directement dans XAML sans espace de noms « x »:<Control />
Drew Noakes
23

Ils sont tous les deux la même chose, de nombreux éléments du framework exposent eux-mêmes une propriété de nom, mais pour ceux qui ne le font pas, vous pouvez utiliser x: name - je reste généralement avec x: name car il fonctionne pour tout.

Les contrôles peuvent s'exposer eux-mêmes comme propriété de dépendance s'ils le souhaitent (car ils doivent utiliser cette propriété de dépendance en interne), ou s'ils peuvent choisir de ne pas le faire.

Plus de détails dans msdn ici et ici :

Certaines applications au niveau du framework WPF peuvent éviter toute utilisation de l'attribut x: Name, car la propriété de dépendance Name spécifiée dans l'espace de noms WPF pour plusieurs des classes de base importantes telles que FrameworkElement / FrameworkContentElement remplit ce même objectif. Il existe encore quelques scénarios XAML et framework courants où l'accès au code d'un élément sans propriété Name est nécessaire, notamment dans certaines classes de support d'animation et de storyboard. Par exemple, vous devez spécifier x: Name sur les lignes de temps et les transformations créées en XAML, si vous avez l'intention de les référencer à partir du code.

Si Name est disponible en tant que propriété sur la classe, Name et x: Name peuvent être utilisés de manière interchangeable en tant qu'attributs, mais une erreur se produira si les deux sont spécifiés sur le même élément.

Steven Robbins
la source
4
S'il n'y a pas de différence, alors pourquoi y aurait-il deux façons de faire la même chose? Les deux manières existaient dans la première version de WPF.
Drew Noakes
@Steve, je n'ai voté contre aucune des réponses à cette question, même si jusqu'à présent aucune n'a été très appropriée.
Drew Noakes
Je ne vois pas comment une réponse qui non seulement vous donne la réponse, mais vous donne également des liens vers MSDN pour plus d'informations sur le sujet n'est pas appropriée? :-)
Steven Robbins
5
@Steve, votre réponse d'origine ne répondait pas à ma question, d'où mon commentaire. Je ne cherche pas une foi aveugle "faites-le de cette façon", mais plutôt une réponse perspicace qui explique pourquoi deux façons existent, même si l'une d'elles fonctionne tout le temps. Techniquement correct! = Approprié. Votre mise à jour est bien meilleure.
Drew Noakes
1
Presque la même réponse ici: wpfwiki.com/WPF%20Q16.4.ashx x: Nom donne au contrôle un nom à utiliser dans le code-behind. Certaines classes fourniront une propriété Name dans le même but. Pour ces classes, il n'y a pas de différence entre x: nom et nom.
Vegar
11

X: le nom peut provoquer des problèmes de mémoire si vous disposez de contrôles personnalisés. Il conservera un emplacement mémoire pour l'entrée NameScope.

Je dis de ne jamais utiliser x: Name sauf si vous le devez.

Scott
la source
D'accord. A travaillé sur une application de kiosque qui avait de nombreuses fuites de mémoire et la résolution de l'équipe de développement précédente consistait simplement à forcer un redémarrage. Une grande partie des fuites ont été facilement identifiées. Pourtant, après avoir corrigé ceux trouvés via IntelliTrace et JustTrace, certaines références échappaient toujours au ramasse-miettes implicite et explicite. J'ai lu: support.scichart.com/index.php?/News/NewsItem/View/21/… J'ai constaté que la réduction de x: Name améliorait encore les performances.
MachinusX
2
Si je comprends bien, cela affecte à la fois Name et x: Name car les deux sont ajoutés à NameScope. Si vous avez besoin d'un nom sur votre élément, il est impossible de le contourner. Vous pouvez reproduire du code sur un élément sans nom via FrameworkElement.RegisterName("elementname"). Cependant, si vous appelez, FrameworkElement.UnregisterName("elementname")cela peut être "déréférencé".
Adam Caviness
8

La seule différence est que si vous utilisez des contrôles utilisateur dans un contrôle du même assemblage, le nom n'identifiera pas votre contrôle et vous obtiendrez une erreur «Utiliser x: nom pour les contrôles du même assemblage». Donc x: Name est la version WPF des contrôles de dénomination dans WPF. Le nom est simplement utilisé comme Winform Legacy. Ils voulaient différencier la dénomination des contrôles dans WPF et winforms car ils utilisent des attributs dans Xaml pour identifier les contrôles des autres assemblys qu'ils utilisaient x: pour les noms de contrôle.

Gardez juste à l'esprit que ne mettez pas de nom pour un contrôle juste pour le garder car il réside dans la mémoire comme un blanc et il vous avertira que Name a été appliqué pour un contrôle mais il n'est jamais utilisé.

Bipul Kumar
la source
8

Nom :

  1. peut être utilisé uniquement pour les descendants de FrameworkElement et FrameworkContentElement;
  2. peut être défini à partir de code-behind via SetValue () et de type propriété.

x: Nom :

  1. peut être utilisé pour presque tous les éléments XAML;
  2. ne peut PAS être défini à partir de code-behind via SetValue (); il ne peut être défini qu'en utilisant la syntaxe d'attribut sur les objets car il s'agit d'une directive.

L'utilisation des deux directives dans XAML pour un FrameworkElement ou FrameworkContentElement provoquera une exception: si le XAML est compilé avec le balisage, l'exception se produira lors de la compilation du balisage, sinon elle se produira lors du chargement.

Oleksandr Zolotarov
la source
7

x:Name signifie: créer un champ dans le code derrière pour contenir une référence à cet objet.

Name signifie: définir la propriété name de cet objet.

itzmebibin
la source
Ce n'est pas tout à fait vrai; ils sont tous les deux accessibles depuis le codebehind, mais curieusement, seul le x: Name peut être mis à jour au moment de l'exécution. Nutty.
4

J'utilise toujours la variante x: Name. Je ne sais pas si cela affecte les performances, je trouve cela plus facile pour la raison suivante. Si vous avez vos propres contrôles utilisateur qui résident dans un autre assembly, la propriété "Name" ne suffira pas toujours. Cela permet de coller plus facilement la propriété x: Name.

Simon
la source
4
S'il n'y a pas de différence, alors pourquoi y aurait-il deux façons de faire la même chose? Les deux manières existaient dans la première version de WPF.
Drew Noakes
3

Ce n'est pas un élément WPF mais un élément XML standard et BtBh y a répondu correctement, x fait référence à l'espace de noms par défaut. En XML, lorsque vous ne préfixez pas un élément / attribut avec un espace de noms, cela suppose que vous voulez l'espace de noms par défaut. Donc, taper Namen'est rien de plus qu'une courte main pour x:Name. Plus de détails sur les espaces de noms XML peuvent être trouvés dans le texte du lien

Robert MacLean
la source
Tenté de -1 x: fait référence à un espace de noms XML différent, c'est vrai, mais ce n'est pas en fait une réponse utile au Q qui concerne le moment où vous devez utiliser l'un ni l'autre. : /
Tim Lovell-Smith
2

L'une des réponses est que x: name doit être utilisé dans différents langages de programme tels que c # et name doit être utilisé pour le framework. Honnêtement, c'est ce que cela me semble.

daddycardona
la source
2

Le x: Name spécifié devient le nom d'un champ qui est créé dans le code sous-jacent lorsque XAML est traité, et ce champ contient une référence à l'objet. Dans Silverlight, à l'aide de l'API managée, le processus de création de ce champ est effectué par les étapes cibles MSBuild, qui sont également chargées de joindre les classes partielles d'un fichier XAML et son code-behind. Ce comportement n'est pas nécessairement spécifié en langage XAML; c'est l'implémentation particulière que Silverlight applique pour utiliser x: Name dans ses modèles de programmation et d'application.

En savoir plus sur MSDN ...

Edd
la source
2

Lorsque vous déclarez un élément Button en XAML, vous faites référence à une classe définie dans le temps d'exécution de Windows appelée Button.

Le bouton a de nombreux attributs tels que l'arrière-plan, le texte, la marge, ..... et un attribut appelé Nom.

Maintenant, lorsque vous déclarez un bouton en XAML, c'est comme créer un objet anonyme qui se trouvait avoir un attribut appelé Nom.

En général, vous ne pouvez pas faire référence à un objet anonyme, mais dans le cadre WPF, le processeur XAML vous permet de faire référence à cet objet par la valeur que vous avez donnée à l'attribut Name.

Jusqu'ici tout va bien.

Une autre façon de créer un objet est de créer un objet nommé au lieu d'un objet anonyme. Dans ce cas, l'espace de noms XAML a un attribut pour un objet appelé Nom (et comme il se trouve dans l'espace de noms XAML, vous avez donc X :) que vous pouvez définir afin que vous puissiez identifier votre objet et y faire référence.

Conclusion:

Le nom est un attribut d'un objet spécifique, mais X: le nom est un attribut de cet objet (il existe une classe qui définit un objet général).

RockyMan Rocky
la source
0

Ma recherche est x:Nameaussi globale variable. Cependant, Namecomme variable locale . Cela signifie-t-il que x: Name vous pouvez l'appeler n'importe où dans votre fichier XAML, mais le nom ne l'est pas.
Exemple:

<StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />
<Button Content="Example" Name="btn" />
</StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />

Vous ne pouvez pas la Bindingpropriété Contentde Buttonavec le nom est "btn" car il en dehorsStackPanel

Phuc Hoang
la source