En WPF, ¿cuáles son las diferencias entre los atributos x: Name y Name?

574

El título lo dice todo. A veces parece que los atributos Namey x:Nameson intercambiables.

Entonces, ¿cuáles son las diferencias definitivas entre ellos y cuándo es preferible usar uno sobre el otro?

¿Hay implicaciones de rendimiento o memoria para usarlas de manera incorrecta?

Drew Noakes
fuente
Las respuestas sugieren que usar x:Nametodo el tiempo funciona bien. Simplemente tuve que cambiarlo, de lo Namecontrario no podría hacer referencia al control en mi código .xaml.cs, así que voy a suponer que ya no es el caso de que funcione bien todo el tiempo.
Ortund
1
Con respecto a su reversión, ¿qué significado adicional le confiere la frase "el título lo dice todo", Drew? ¿No es redundante? (Mi razón para editar es que tiendo a desalentar las frases de relleno conversacionales; esto no es más informativo que "Me pregunto si puedes ayudarme").
halfer

Respuestas:

481

Realmente solo hay un nombre en XAML, el x:Name. Un marco de trabajo, como WPF, puede asignar opcionalmente una de sus propiedades a XAML x:Namemediante el uso de RuntimeNamePropertyAttributeen la clase que designa una de las propiedades de las clases como asignación al atributo x: Name de XAML.

La razón por la que se hizo esto fue para permitir marcos que ya tienen un concepto de "Nombre" en tiempo de ejecución, como WPF. En WPF, por ejemplo, FrameworkElementintroduce una propiedad Name.

En general, una clase no necesita almacenar el nombre para x:Nameser utilizable. Todos los x:Namemedios para XAML es generar un campo para almacenar el valor en el código detrás de la clase. Lo que hace el tiempo de ejecución con esa asignación depende del marco.

Entonces, ¿por qué hay dos formas de hacer lo mismo? La respuesta simple es porque hay dos conceptos asignados en una propiedad. WPF quiere el nombre de un elemento preservado en tiempo de ejecución (que se puede usar a través de Bind, entre otras cosas) y XAML necesita saber a qué elementos desea que sean accesibles los campos en el código detrás de la clase. WPF une estos dos juntos marcando la propiedad Name como un alias de x: Name.

En el futuro, XAML tendrá más usos para x: Nombre, como permitirle establecer propiedades haciendo referencia a otros objetos por nombre, pero en 3.5 y anteriores, solo se usa para crear campos.

Si debe usar uno u otro es realmente una pregunta de estilo, no técnica. Dejaré eso a otros para una recomendación.

Consulte también AutomationProperties.Name VS x: Name , AutomationProperties.Name es utilizado por las herramientas de accesibilidad y algunas herramientas de prueba.

chuckj
fuente
2
En Visual Studio 2010, la propiedad Nombre se establece (no x: Nombre) cuando edita XAML a través del diseñador. Parece que MS alienta el uso de Name sobre x: Name, así que supongo que ese es el estándar de facto.
Nebulosa
11
No creo que los dos sean intercambiables en general. Los controles de nombre de usuario requieren x:Nameporque Nameno crearía un campo para ser reconocido en código subyacente. Sin embargo, todavía no sé por qué sucede esto.
Libor
55
No son ni quise decir que lo hicieron. En WPF, si un elemento tiene una Namepropiedad, significan lo mismo. Si el elemento no tiene una Namepropiedad, debe usarlo x:Name.
chuckj
90

No són la misma cosa.

x:Namees un concepto xaml, usado principalmente para hacer referencia a elementos. Cuando le da a un elemento el atributo x: Name xaml, "lo especificado se x:Nameconvierte en el nombre de un campo que se crea en el código subyacente cuando se procesa xaml, y ese campo contiene una referencia al objeto". ( MSDN ) Entonces, es un campo generado por el diseñador, que tiene acceso interno por defecto.

Namees la propiedad de cadena existente de a FrameworkElement, listada como cualquier otra propiedad de elemento wpf en forma de un atributo xaml.

Como consecuencia, esto también significa que x:Namese puede utilizar en una gama más amplia de objetos. Esta es una técnica para permitir que cualquier cosa en xaml sea referenciada por un nombre dado.

Kenan EK
fuente
66
Entonces, ¿por qué se puede usar Name o x: Name con Binding.ElementName? Parece que el atributo x: Name no solo se usa para nombrar un campo en el código generado, sino que también está disponible en metadatos en tiempo de ejecución.
Drew Noakes
Es un campo generado como el nombre del campo en las propiedades de diseño del editor WinForms. Allí coloca un nombre en la lista de propiedades y se convierte en el nombre de un campo. Este es el mismo comportamiento. Por supuesto, está disponible en tiempo de ejecución ya que es un campo interno compilado en el código subyacente. Binding.ElementName verifica para cualquier caso, ese es el editor de xaml "magic", el x: Name no es mágico en sí mismo.
Kenan EK
39

x: Nombre y Nombre hacen referencia a diferentes espacios de nombres.

x: name es una referencia al espacio de nombres x definido por defecto en la parte superior del archivo Xaml.

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

Solo decir que Nombre usa el espacio de nombres predeterminado debajo.

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

x: Nombre dice usar el espacio de nombres que tiene el alias x . x es el valor predeterminado y la mayoría de las personas lo dejan, pero puedes cambiarlo a lo que quieras

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

entonces su referencia sería foo: nombre

Definir y usar espacios de nombres en WPF


OK, veamos esto de una manera diferente. Supongamos que arrastra y suelta un botón en su página Xaml. Puede hacer referencia a esto de 2 maneras x: nombre y nombre . Todos xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" y xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml" son referencias a múltiples espacios de nombres . Dado que xaml contiene el espacio de nombres Control (no 100% en eso) y la presentación contiene el FrameworkElement AND, la clase Button tiene un patrón de herencia de:

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

Entonces, como era de esperar, cualquier cosa que herede de FrameworkElement tendría acceso a todos sus atributos públicos. entonces, en el caso de Button, obtiene su atributo Name de FrameworkElement, en la parte superior del árbol de jerarquía. Entonces puede decir x: Name o Name y ambos accederán al getter / setter desde FrameworkElement.

Referencia de MSDN

WPF define un atributo CLR que consumen los procesadores XAML para asignar múltiples espacios de nombres CLR a un solo espacio de nombres XML. El atributo XmlnsDefinitionAttribute se coloca en el nivel de ensamblado en el código fuente que produce el ensamblaje. El código fuente del ensamblado WPF usa este atributo para asignar los diversos espacios de nombres comunes, como System.Windows y System.Windows.Controls, al http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace.

Entonces los atributos de ensamblaje se verán así:

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
fuente
1
Creo que no es cierto que http://schemas.microsoft.com/winfx/2006/xamlposee Controlya que se puede utilizar directamente en XAML sin una 'x' espacio de nombres:<Control />
a Drew Noakes
23

Ambas son lo mismo, muchos elementos de marco exponen una propiedad de nombre, pero para aquellos que no pueden usar x: name: generalmente solo me quedo con x: name porque funciona para todo.

Los controles pueden exponer el nombre como una Propiedad de dependencia si así lo desean (porque necesitan usar esa Propiedad de dependencia internamente), o pueden elegir no hacerlo.

Más detalles en msdn aquí y aquí :

Algunas aplicaciones de nivel de marco de WPF podrían evitar el uso del atributo x: Name, porque la propiedad de dependencia de Nombre como se especifica dentro del espacio de nombres de WPF para varias de las clases base importantes como FrameworkElement / FrameworkContentElement cumple este mismo propósito. Todavía hay algunos escenarios comunes de XAML y framework donde es necesario el acceso de código a un elemento sin propiedad Name, especialmente en ciertas clases de animación y soporte de guiones gráficos. Por ejemplo, debe especificar x: Nombre en líneas de tiempo y transformaciones creadas en XAML, si tiene la intención de hacer referencia a ellas desde el código.

Si Name está disponible como una propiedad en la clase, Name yx: Name se pueden usar indistintamente como atributos, pero se producirá un error si ambos se especifican en el mismo elemento.

Steven Robbins
fuente
44
Si no hay diferencia, ¿por qué habría dos formas de hacer lo mismo? Ambas formas existieron en el primer lanzamiento de WPF.
Drew Noakes
@ Steve, no rechacé ninguna de las respuestas a esta pregunta, a pesar de que ninguna de ellas ha sido muy apropiada hasta ahora.
Drew Noakes
No veo cómo una respuesta que no solo te da la respuesta, sino que también te da enlaces a MSDN para obtener más información sobre el tema, ¿no es apropiada? :-)
Steven Robbins
55
@Steve su respuesta original no abordó mi pregunta, de ahí mi comentario. No busco la fe ciega "hágalo de esta manera", sino una respuesta perspicaz que explica por qué existen dos formas, incluso si una de ellas funciona todo el tiempo. Técnicamente correcto! = Apropiado. Tu actualización es mucho mejor.
Drew Noakes
1
La misma respuesta aquí: wpfwiki.com/WPF%20Q16.4.ashx x: los nombres le están dando al control un nombre para usar en el código subyacente. Algunas clases proporcionarán una propiedad de nombre para el mismo propósito. Para estas clases, no hay diferencia entre x: nombre y nombre.
Vegar
11

X: El nombre puede causar problemas de memoria si tiene controles personalizados. Mantendrá una ubicación de memoria para la entrada NameScope.

Yo digo que nunca uses x: Nombre a menos que tengas que hacerlo.

Scott
fuente
Convenido. Trabajé en una aplicación de kiosco que tenía numerosas pérdidas de memoria y la resolución del equipo de desarrollo anterior era solo forzar un reinicio. Gran parte de las filtraciones se identificaron fácilmente. Sin embargo, después de corregir los que se encuentran a través de IntelliTrace y JustTrace, algunas referencias aún eludieron la recolección de basura implícita y explícita. Leí: support.scichart.com/index.php?/News/NewsItem/View/21/… Se encontró que la reducción de x: Nombre mejora aún más el rendimiento.
MachinusX
2
Según tengo entendido, esto afecta tanto a Name como a x: Name, ya que ambos se agregan a NameScope. Si necesita un nombre en su elemento, no hay forma de evitarlo. Puede repro en el código de un elemento sin nombre a través de FrameworkElement.RegisterName("elementname"). Sin embargo, si lo llama FrameworkElement.UnregisterName("elementname")puede ser "desreferenciado".
Adam Caviness
8

La única diferencia es que si está utilizando los controles de usuario en un control de Same Assembly, Name no identificará su control y obtendrá un error "Use x: Name para controles en el mismo ensamblaje". Entonces x: Nombre es el control de versiones WPF de los controles de nombres en WPF. El nombre solo se usa como Winform Legacy. Querían diferenciar los nombres de los controles en WPF y winforms ya que usan atributos en Xaml para identificar controles de otros ensamblados que usaron x: para Nombres de control.

Solo tenga en cuenta que no ponga un nombre para un control solo por mantenerlo, ya que reside en la memoria como un espacio en blanco y le dará una advertencia de que Nombre se ha aplicado para un control pero nunca se usa.

Bipul Kumar
fuente
8

Nombre :

  1. solo se puede usar para descendientes de FrameworkElement y FrameworkContentElement;
  2. se puede establecer desde el código subyacente a través de SetValue () y como propiedad.

x: Nombre :

  1. se puede usar para casi todos los elementos XAML;
  2. NO se puede establecer desde el código subyacente a través de SetValue (); solo se puede establecer usando la sintaxis de atributo en los objetos porque es una directiva.

El uso de ambas directivas en XAML para un FrameworkElement o FrameworkContentElement provocará una excepción: si el XAML se compila de marcado, la excepción se producirá en la compilación de marcado, de lo contrario se produce en la carga.

Oleksandr Zolotarov
fuente
7

x:Name significa: crear un campo en el código detrás para contener una referencia a este objeto.

Name significa: establecer la propiedad de nombre de este objeto.

itzmebibin
fuente
Esto no es del todo cierto; ambos son accesibles desde el código subyacente, pero curiosamente solo el x: Name se puede actualizar en tiempo de ejecución. De nuez.
4

Siempre uso la variante x: Nombre. No tengo idea si esto afecta el rendimiento, solo me resulta más fácil por la siguiente razón. Si tiene sus propios controles de usuario que residen en otro ensamblado, la propiedad "Nombre" no siempre será suficiente. Esto hace que sea más fácil pegar también la propiedad x: Name.

Simón
fuente
44
Si no hay diferencia, ¿por qué habría dos formas de hacer lo mismo? Ambas formas existieron en el primer lanzamiento de WPF.
Drew Noakes
3

No es un elemento WPF sino un XML estándar y BtBh lo ha respondido correctamente, x se refiere al espacio de nombres predeterminado. En XML, cuando no prefija un elemento / atributo con un espacio de nombres, se supone que desea el espacio de nombres predeterminado. Entonces escribir simplemente Nameno es más que una mano corta x:Name. Puede encontrar más detalles sobre los espacios de nombres XML en el texto del enlace

Robert MacLean
fuente
Tentado a -1 x: se refiere a un espacio de nombres XML diferente, verdadero, pero esa no es realmente una respuesta útil a la Q, que se trata de cuándo necesita usar uno sin el otro. : /
Tim Lovell-Smith
2

Una de las respuestas es que x: name debe usarse dentro de diferentes lenguajes de programa, como c #, y name debe usarse para el marco. Sinceramente, eso es lo que me suena.

daddycardona
fuente
2

El x: Name especificado se convierte en el nombre de un campo que se crea en el código subyacente cuando se procesa XAML, y ese campo contiene una referencia al objeto. En Silverlight, utilizando la API administrada, el proceso de creación de este campo se realiza mediante los pasos de destino de MSBuild, que también son responsables de unir las clases parciales para un archivo XAML y su código subyacente. Este comportamiento no se especifica necesariamente en lenguaje XAML; es la implementación particular que Silverlight aplica para usar x: Name en sus modelos de programación y aplicación.

Leer más en MSDN ...

Edd
fuente
2

Cuando declara un elemento Button en XAML, se refiere a una clase definida en tiempo de ejecución de Windows llamada Button.

El botón tiene muchos atributos, como fondo, texto, margen, ..... y un atributo llamado Nombre.

Ahora, cuando declaras un botón en XAML, es como crear un objeto anónimo que tiene un atributo llamado Nombre.

En general, no puede hacer referencia a un objeto anónimo, pero en el marco de trabajo WPF, el procesador XAML le permite referirse a ese objeto por cualquier valor que haya otorgado al atributo Name.

Hasta aquí todo bien.

Otra forma de crear un objeto es crear un objeto con nombre en lugar de un objeto anónimo. En este caso, el espacio de nombres XAML tiene un atributo para un objeto llamado Nombre (y dado que está en el espacio de nombres XAML, tiene X :) que puede configurar para que pueda identificar su objeto y consultarlo.

Conclusión:

Nombre es un atributo de un objeto específico, pero X: Nombre es un atributo de ese objeto (hay una clase que define un objeto general).

RockyMan Rocky
fuente
0

Mi investigación es x:Namecomo variable global . Sin embargo, Namecomo variable local . ¿Eso significa x: Nombre que puede llamarlo en cualquier parte de su archivo XAML pero Nombre no lo es.
Ejemplo:

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

No se puede Bindingpropiedad Contentde Buttoncon Nombre es "btn" porque fueraStackPanel

Phuc Hoang
fuente