Detalles de la sintaxis XAML

En este tema se definen los términos que se utilizan para describir los elementos de sintaxis de XAML. Estos términos se utilizan con frecuencia a lo largo de esta documentación, en la documentación de WPF específicamente y de otros marcos que utilizan XAML o los conceptos de XAML básicos habilitados por la compatibilidad del lenguaje XAML en el nivel de System.Xaml. En este tema se desarrolla la terminología básica presentada en el tema Información general sobre XAML (WPF).

Este tema contiene las secciones siguientes.

  • Especificación del lenguaje XAML
  • XAML y CLR
  • Sintaxis de elementos de objeto
  • Propiedades de los elementos de objeto
  • Sintaxis de atributos (propiedades)
  • Sintaxis de elementos de propiedad
  • Sintaxis de colecciones
  • Propiedades del contenido XAML
  • Propiedades de contenido y sintaxis de colección combinadas
  • Espacios de nombres XAML
  • Extensiones de marcado
  • Propiedades asociadas
  • Eventos asociados
  • Anatomía de un elemento raíz XAML
  • Usos opcionales y no recomendados de XAML
  • Temas relacionados

Especificación del lenguaje XAML

La terminología de la sintaxis de XAML definida aquí también se define o se hace referencia a ella dentro de la especificación del lenguaje XAML. XAML es un lenguaje basado en XML y sigue las reglas estructurales de XML. Parte de esta terminología la comparte con o está basada en la terminología utilizada normalmente al describir el lenguaje XML o el modelo de objetos de documento de XML.

Para obtener más información sobre la especificación del lenguaje XAML, descargue [MS-XAML] del Centro de descargas de Microsoft.

XAML y CLR

XAML es un lenguaje de marcado. common language runtime (CLR), como su nombre indica, habilita la ejecución en tiempo de ejecución. XAML en sí mismo no es uno de los lenguajes comunes que utiliza directamente el runtime de CLR. En cambio, puede considerarse que XAML respalda su propio sistema de tipos. El sistema de análisis de XAML determinado WPF utiliza se basa en el CLR y en el sistema de tipos de CLR. Los tipos XAML se asignan a los tipos CLR para crear instancias de una representación en tiempo de ejecución cuando se analiza el XAML para WPF. Por esta razón, el resto de la explicación de la sintaxis de este documento incluirá referencias al sistema de tipos de CLR, aunque las explicaciones de sintaxis equivalentes de la especificación del lenguaje XAML no las incluyen. (Según el nivel de la especificación del lenguaje XAML, los tipos XAML se podrían asignar a cualquier otro sistema de tipos, que no tiene que ser el CLR, pero para ello se necesitaría la creación y uso de un analizador de XAML diferente).

Miembros de tipos y herencia de clases

Las propiedades y los eventos, cuando aparecen como miembros XAML de un tipo de WPF, a menudo se heredan de los tipos base. Por ejemplo, considere este ejemplo: <Button Background="Blue" .../>. La propiedad Background no es una propiedad declarada inmediatamente en la clase Button, si se examina la definición de clase, los resultados de la reflexión o la documentación. En su lugar, Background se hereda de la clase Control base.

El comportamiento de la herencia de clases de los elementos XAML de WPF es una desviación significativa de la interpretación exigida por esquema del marcado XML. La herencia de clases puede ser compleja, en concreto cuando las clases base intermedias son abstractas o cuando implican interfaces. Esta es una de las razones por las que el conjunto de elementos de XAML y sus atributos permitidos resulta complicada de representar correcta y completamente utilizando los tipos de esquema que se usan normalmente para la programación en XML, como los formatos DTD o XSD. Otra razón es que la extensibilidad y las características de asignación de tipos del lenguaje XAML evitan la integridad de cualquier representación fija de los tipos y miembros permitidos.

Sintaxis de elementos de objeto

La sintaxis de elementos de objeto es la sintaxis del marcado XAML que crea instancias de una clase o estructura CLR declarando un elemento XML. Esta sintaxis se parece a la sintaxis de elementos de otros lenguajes de marcado, como HTML. La sintaxis de elementos de objeto comienza con un corchete angular izquierdo (<), seguido inmediatamente por el nombre de tipo de la clase o estructura cuyas instancias se van a crear. Puede haber cero o más espacios después del nombre de tipo y se pueden declarar cero o más atributos en el elemento de objeto; cada pareja de nombre de atributo="valor" estará separada por uno o más espacios. Por último, debe cumplirse una de las condiciones siguientes:

  • El elemento y la etiqueta deben cerrarse mediante una barra diagonal (/), seguida inmediatamente por un corchete angular derecho (>).

  • La etiqueta de apertura debe completarse con un corchete angular derecho (>). Dicha etiqueta puede ir seguida de otros elementos de objeto, de elementos de propiedad o de texto interno. El contenido se puede incluir aquí exactamente está restringido por el modelo de objetos del elemento. También debe existir la etiqueta de cierre equivalente para el elemento de objeto, anidada y equilibrada correctamente con otras parejas de etiquetas de apertura y cierre.

XAML como lo implementa .NET tiene un conjunto de reglas que asignan los elementos de objeto a tipos, los atributos a propiedades o eventos, y los espacios de nombres XAML a espacios de nombres CLR, más el ensamblado. Para WPF y .NET Framework, los elementos de objeto XAML se asignan a los tipos Microsoft .NET como se definen en los ensamblados a los que se hace referencia, y los atributos se asignan a los miembros de esos tipos. Cuando se hace referencia a un tipo CLR en XAML, también se tiene el acceso a los miembros heredados de ese tipo.

Por ejemplo, el ejemplo siguiente es una sintaxis de elementos de objeto que crea una nueva instancia de la clase Button y también especifica un atributo Name y un valor para ese atributo:

<Button Name="CheckoutButton"/>

El ejemplo siguiente es una sintaxis de elementos de objeto que también incluye la sintaxis de propiedad de contenido de XAML. El texto interno incluido dentro se utilizará para establecer la propiedad de contenido de TextBox de XAML, Text.

<TextBox>This is a Text Box</TextBox>

Modelos de contenido

Una clase podría admitir su uso como un elemento de objeto XAML en lo referente a la sintaxis, pero dicho elemento sólo funcionará correctamente en una aplicación o página si se coloca en una posición esperada de un modelo de contenido o árbol de elementos general. Por ejemplo, un elemento MenuItem se debería colocar normalmente sólo como un elemento secundario de una clase derivada de MenuBase, como Menu. Los modelos de contenido para elementos concretos se documentan como parte de los comentarios en las páginas de la clase para los controles y otras clases de WPF que se pueden utilizar como elementos XAML.

Propiedades de los elementos de objeto

Las propiedades XAML se establecen mediante diversas sintaxis posibles. Las sintaxis que se pueden utilizar para una propiedad determinada variarán, dependiendo de las características del sistema de tipos subyacente de la propiedad que se está estableciendo.

Estableciendo los valores de propiedad, se agregan características a los objetos según existen en el gráfico de objetos del tiempo de ejecución. El estado inicial del objeto creado de un elemento de objeto está basado en el comportamiento del constructor predeterminado. Normalmente, la aplicación utilizará algo distinto de una instancia completamente predeterminada de cualquier objeto dado.

Sintaxis de atributos (propiedades)

La sintaxis de atributos es la sintaxis del marcado XAML que establece un valor para una propiedad declarando un atributo en un elemento de objeto existente. El nombre de atributo debe coincidir con el nombre del miembro CLR de la propiedad de la clase que respalda al elemento de objeto pertinente. El nombre del atributo va seguido de un operador de asignación (=). El valor de atributo debe ser una cadena encerrada entre comillas.

NotaNota

Se pueden utilizar comillas alternas para poner una comilla literal en un atributo.Por ejemplo, puede utilizar comillas simples como medio para declarar una cadena que contiene un carácter de comilla doble en su interior.Tanto si se utilizan comillas simples como si se utilizan dobles, se debe utilizar la pareja correspondiente para abrir y cerrar la cadena de valor del atributo.También hay secuencias de escape y otras técnicas disponibles para evitar las restricciones de caracteres impuesta por una sintaxis XAML determinada.Vea Entidades de caracteres XML y XAML.

Para que una propiedad sea establecida a través de la sintaxis de atributo, debe ser pública y grabable. El valor de la propiedad en el sistema de tipos de respaldo debe ser un tipo de valor o un tipo de referencia del que se puedan crear instancias o al que pueda hacer referencia un procesador XAML cuando tiene acceso al tipo de respaldo pertinente.

Para los eventos XAML de WPF, el evento al que se hace referencia como nombre de atributo debe ser público y tener un delegado público.

La propiedad o el evento debe ser un miembro de la clase o estructura de la que el elemento de objeto contenedor crea una instancia.

Procesamiento de los valores de atributo

El valor de cadena incluido entre las comillas de apertura y cierre es procesado por un procesador XAML. En el caso de las propiedades, el comportamiento de procesamiento predeterminado está definido por el tipo de propiedad CLR subyacente.

El valor de atributo se rellena con uno de los valores siguientes, en el orden de procesamiento indicado a continuación:

  1. Si el procesador XAML encuentra una llave o un elemento de objeto que se deriva de MarkupExtension, se evalúa primero la extensión de marcado a la que se hace referencia, en lugar de procesar el valor como una cadena, y se utiliza como valor el objeto devuelto por la extensión de marcado. En muchos casos, el objeto devuelto por una extensión de marcado no será un objeto cuya instancia se acabe de crear, sino una referencia a un objeto existente o una expresión que aplaza la evaluación hasta el momento de la ejecución.

  2. Si la propiedad se declara con un TypeConverter con atributos, o el tipo de valor de esa propiedad se declara con un TypeConverter con atributos, el valor de cadena del atributo se envía al convertidor de tipos como una entrada de conversión y el convertidor devolverá una nueva instancia de objeto.

  3. Si no hay TypeConverter, se intenta una conversión directa al tipo de propiedad. Este nivel final es una conversión directa en el valor analizador nativo entre los tipos primitivos del lenguaje XAML o una comprobación de los nombres de constantes con nombre en una enumeración (el analizador tiene acceso a los valores correspondientes).

Valores de atributo de enumeración

En XAML, las enumeraciones las procesan los analizadores de XAML intrínsecamente, y los miembros de una enumeración deben especificarse mediante el nombre de cadena de una de las constantes con nombre de la enumeración.

Para los valores de enumeración sin marcadores, el comportamiento nativo consiste en procesar la cadena de un valor de atributo y resolverlo como uno de los valores de enumeración. La enumeración no se especifica en el formato Enumeración.Valor, tal y como se hace en el código. En su lugar, sólo se especifica Valor, y Enumeración se deduce a partir del tipo de la propiedad que se está estableciendo. Si se especifica un atributo en la forma Enumeración.Valor, no se resolverá correctamente.

Para las enumeraciones basadas en marcadores, el comportamiento está basado en el método Enum.Parse. Se pueden especificar varios valores para una enumeración basada en marcadores separando cada valor con una coma. Sin embargo, no es posible combinar valores de enumeración que no estén basados en marcadores. Por ejemplo, no se puede utilizar la sintaxis de comas para intentar crear un valor Trigger que actúe en varias condiciones de una enumeración sin marcadores:

<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
  <Setter ... />
</Trigger>
...

Las enumeraciones basadas en marcadores que admiten atributos que se pueden establecer en XAML no son frecuentes en WPF. Sin embargo, una de estas enumeraciones es StyleSimulations. Por ejemplo, se puede utilizar la sintaxis de atributo basada en marcadores separada por comas para modificar el ejemplo proporcionado en las Notas de la clase Glyphs; StyleSimulations = "BoldSimulation" podría convertirse en StyleSimulations = "BoldSimulation,ItalicSimulation". KeyBinding.Modifiers es otra propiedad en la que se puede especificar más de un valor de enumeración. Sin embargo, esta propiedad es un caso especial, ya que la enumeración ModifierKeys admite su propio convertidor de tipos. El convertidor de tipos para los modificadores usa un signo más (+) como delimitador, en lugar de una coma (). Esta conversión admite la sintaxis más tradicional para representar las combinaciones de teclas en la programación de Microsoft Windows, como "Ctrl+Alt".

Referencias a nombres de miembros de evento y a propiedades

Al especificar un atributo, se puede hacer referencia a cualquier propiedad o evento que exista como un miembro del tipo de CLR cuya instancia se ha creado para el elemento de objeto contenedor.

O bien, se puede hacer referencia a una propiedad o evento asociado, independiente del elemento de objeto contenedor. (Las propiedades adjuntas se explican más adelante en otra sección.)

Asimismo, puede asignar un nombre a cualquier evento desde cualquier objeto que sea accesible a través del espacio de nombres predeterminado utilizando un nombre parcial nombreDeTipo.evento; esta sintaxis permite asociar controladores para eventos enrutados en los que el controlador está diseñado para controlar eventos con enrutamiento desde elementos secundarios, pero donde el elemento primario no tiene ese evento en su tabla de miembros. Esta sintaxis se parece a la sintaxis de eventos asociados, pero en este caso el evento no es un verdadero evento asociado. En su lugar, se hace referencia a un evento con un nombre completo. Para obtener más información, consulte Información general sobre eventos enrutados.

En algunos escenarios, los nombres de propiedad se proporcionan a veces como el valor de un atributo, en lugar del nombre de atributo. Ese nombre de propiedad también puede incluir calificadores, como la propiedad especificada con la forma ownerType.dependencyPropertyName. Este escenario es habitual al crear estilos o plantillas en XAML. Las reglas de procesamiento para los nombres de propiedad proporcionados como un valor de atributo son diferentes y se rigen por el tipo de la propiedad que se está estableciendo o por los comportamientos de subsistemas WPF determinados. Para obtener información detallada, vea Aplicar estilos y plantillas.

Otro uso para los nombres de propiedades se da cuando un valor de atributo describe una relación entre propiedades. Esta característica se utiliza para el enlace de datos y para los destinos de guión gráfico, y está habilitada por la clase PropertyPath y su convertidor de tipos. Para obtener una descripción más completa de la semántica de búsqueda, vea Sintaxis de PropertyPath de XAML.

Sintaxis de elementos de propiedad

La sintaxis de elementos de propiedad es una sintaxis que difiere ligeramente de las reglas básicas de la sintaxis de XML para elementos. En XML, el valor de un atributo es de hecho una cadena y la única variación posible es el formato de codificación de cadenas que se utiliza. En XAML, puede asignar otros elementos de objeto como valores de las propiedades. Esta función está habilitada por la sintaxis de elementos de propiedad. En lugar de especificar la propiedad como un atributo dentro de la etiqueta de elemento, la propiedad se especifica utilizando una etiqueta de elemento de apertura en la forma nombreDeTipoElemento.nombreDePropiedad, se especifica el valor de la propiedad en su interior y, a continuación, se cierra el elemento de propiedad.

Concretamente, la sintaxis comienza con un corchete angular izquierdo (<), seguido inmediatamente por el nombre de tipo de la clase o estructura en la que está incluida la sintaxis de elementos de propiedad. Esto va seguido inmediatamente de un solo punto (.), el nombre de una propiedad y, por último, un corchete angular de cierre (>). Como sucede con la sintaxis de atributo, esa propiedad debe existir dentro de los miembros públicos declarados del tipo especificado. El valor que se va a asignar a la propiedad se incluye dentro del elemento de propiedad. Normalmente, el valor se proporciona como uno o más elementos de objeto, porque la especificación de objetos como valores es el escenario que la sintaxis de elementos de propiedad pretende resolver. Finalmente, se debe proporcionar una etiqueta de cierre equivalente que especifique la misma combinación nombreDeTipoElemento.nombreDePropiedad, anidada y equilibrada correctamente con otras etiquetas de elemento.

Por ejemplo, la sintaxis siguiente es la sintaxis de elementos de propiedad para la propiedad ContextMenu de un objeto Button.

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

El valor contenido en un elemento de propiedad también se puede proporcionar como texto interno, en aquellos casos en que el tipo de propiedad que se especifica es un tipo de valor primitivo, como String, o una enumeración en la que se especifica un nombre. Estos dos usos no son habituales, porque cada uno de estos casos también podría utilizar una sintaxis de atributo más sencilla. Un escenario para rellenar un elemento de propiedad con una cadena es para las propiedades que no son la propiedad de contenido de XAML pero que se utilizan para la representación de texto de la interfaz de usuario, en el que se requiere que aparezcan elementos de espacio en blanco determinados, como avances de línea. La sintaxis de atributo no puede conservar los avances de línea, pero la sintaxis de elementos de propiedad sí, siempre que esté activa la conservación de espacios en blanco significativos (para obtener más información, vea Procesamiento de espacios en blanco en XAML). Otro escenario es aquel en el que x:Uid (Directiva) se puede aplicar al elemento de propiedad y así marcar el valor interno como un valor que debería estar localizado en el BAML de WPF u otras técnicas.

Un elemento de propiedad no se representa en el árbol lógico de WPF. Un elemento de propiedad no es más que una sintaxis determinada para establecer una propiedad, y no es ningún elemento que tenga una instancia o un objeto que lo respalde. (Para obtener detalles sobre el concepto de árbol lógico, vea Árboles en WPF.)

En las propiedades en las que se admite tanto la sintaxis de atributo como la sintaxis de elementos de propiedad, ambas sintaxis tienen normalmente el mismo resultado, aunque algunos detalles como el control del espacio en blanco pueden variar ligeramente entre ellas.

Sintaxis de colecciones

La especificación XAML exige que las implementaciones de procesador de XAML identifiquen las propiedades cuyo tipo de valor sea una colección. La implementación general de procesadores XAML en .NET está basada en código administrado y en el CLR, e identifica los tipos de colección mediante uno de los mecanismos siguientes:

Si el tipo de una propiedad es una colección, no es necesario especificar en el marcado el tipo de colección que se infiere como elemento de objeto. En su lugar, los elementos que van a convertirse en elementos de la colección se especifican como uno o más elementos secundarios del elemento de propiedad. Cada uno de estos elementos se evalúa como un objeto durante la carga y se agrega a la colección llamando al método Add de la colección implícita. Por ejemplo, la propiedad Triggers de Style toma el tipo de colección especializado TriggerCollection, que implementa IList. No es necesario crear instancias de un elemento de objeto TriggerCollection en el marcado. En su lugar, especifique uno o varios elementos Trigger como elementos dentro del elemento de propiedad Style.Triggers, donde Trigger (o una clase derivada) es el tipo que se espera como tipo de elemento para el objeto TriggerCollection con establecimiento inflexible de tipos e implícito.

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

Una propiedad puede ser un tipo de colección y la propiedad de contenido de XAML de ese tipo y de los tipos derivados. Esto se explica en la sección siguiente de este tema.

Un elemento de colección implícito crea un miembro en la representación del árbol lógico, aunque no aparece en el marcado como un elemento. Normalmente, el constructor del tipo primario realiza la creación de instancias para la colección que es una de sus propiedades, y la colección, que inicialmente estaba vacía, pasa a formar parte del árbol de objetos.

NotaNota

La lista genérica y las interfaces de diccionario (IList<T> y IDictionary<TKey, TValue>) no son compatibles con la detección de colecciones.Sin embargo, puede utilizar List<T> como una clase base, ya que implementa directamente IList o Dictionary<TKey, TValue>, ya que ésta implementa directamente IDictionary.

En las páginas de referencia de .NET Framework para los tipos de colección, en las secciones de sintaxis de XAML se hace referencia de forma ocasional a esta sintaxis, con la omisión deliberada del elemento de objeto, como sintaxis de colección implícita.

Con la excepción del elemento raíz, cada elemento de objeto de un archivo XAML que está anidado como elemento secundario de otro elemento es realmente un elemento que tiene una de las características siguientes o ambas: es un miembro de una propiedad de colección implícita de su elemento primario o un elemento que especifica el valor de la propiedad de contenido de XAML para el elemento primario (las propiedades de contenido de XAML se describirán en una sección posterior). En otras palabras, la relación entre elementos primarios y secundarios en una página de marcado es realmente un objeto único en la raíz, y cada elemento de objeto que está debajo de la raíz es una instancia única que proporciona un valor de propiedad del elemento primario o uno de los elementos dentro de una colección que es también un valor de propiedad de tipo de colección del elemento primario. Este concepto de raíz única es común en XML y se refuerza con frecuencia en el comportamiento de las API que cargan XAML como Load.

En el ejemplo siguiente se muestra una sintaxis con el elemento de objeto para una colección (GradientStopCollection) que se especifica explícitamente.

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="Blue" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Observe que no siempre es posible declarar la colección explícitamente. Por ejemplo, intentar declarar TriggerCollection explícitamente en el ejemplo anterior de Triggers produciría un error. Para declarar la colección explícitamente es preciso que la clase de colección admita un constructor predeterminado, y TriggerCollection no tiene un constructor predeterminado.

Propiedades del contenido XAML

La sintaxis de contenido XAML es una sintaxis que sólo está habilitada en las clases que especifican ContentPropertyAttribute como parte de su declaración de clase. ContentPropertyAttribute hace referencia al nombre de propiedad que es la propiedad de contenido correspondiente a ese tipo de elemento (incluidas las clases derivadas). Cuando los procesa un procesador XAML, los elementos secundarios o el texto interno que se encuentran entre las etiquetas de apertura y cierre del elemento de objeto se asignarán como el valor de la propiedad de contenido de XAML de ese objeto. Es posible especificar elementos de propiedad explícitos para la propiedad de contenido, pero este uso no se suele mostrar en las secciones de sintaxis XAML de la referencia de .NET Framework. La técnica explícita/detallada técnica resulta útil a veces para aumentar la claridad del marcado o por motivos de estilo de marcado; sin embargo, en general, la intención de una propiedad de contenido es simplificar el marcado para que los elementos que poseen una relación intuitiva de tipo elemento primario-elemento secundario se puedan anidar directamente. Las etiquetas de los elementos de propiedad de las demás propiedades de un elemento no se asignan como "contenido" por una definición estricta de lenguaje XAML; se procesan previamente en el orden de procesamiento del analizador XAML y no se las considera "contenido".

Los valores de las propiedades de contenido XAML deben ser contiguos

El valor de una propiedad de contenido de XAML se debe proporcionar exclusivamente antes o exclusivamente después de cualquier otro elemento de propiedad en ese elemento de objeto. Esto es cierto independientemente de si el valor de una propiedad de contenido de XAML se especifica como una cadena o como uno o varios objetos. Por ejemplo, el marcado siguiente no se puede analizar:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

Esto no es válido básicamente porque si esta sintaxis se hiciera explícita utilizando la sintaxis de elementos de propiedad para la propiedad de contenido, ésta se establecería dos veces:

<Button>
  <Button.Content>I am a </Button.Content>
  <Button.Background>Blue</Button.Background>
  <Button.Content> blue button</Button.Content>
</Button>

Un ejemplo similar que tampoco es válido se da cuando la propiedad de contenido es una colección y los elementos secundarios están intercalados con los elementos de propiedad:

<StackPanel>
  <Button>This example</Button>
  <StackPanel.Resources>
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
  </StackPanel.Resources>
  <Button>... is illegal XAML</Button>
</StackPanel>

Propiedades de contenido y sintaxis de colección combinadas

Para aceptar varios elementos de objeto como contenido, el tipo de la propiedad de contenido debe ser específicamente un tipo de colección. De forma similar a la sintaxis de elementos de propiedad para los tipos de colección, un procesador XAML debe identificar los tipos que son tipos de colección. Si un elemento tiene una propiedad de contenido de XAML y el tipo de la propiedad de contenido de XAML es una colección, no es necesario especificar el tipo de colección implícito en el marcado como un elemento de objeto, ni especificar la propiedad de contenido de XAML como elemento de propiedad. Por consiguiente, el modelo de contenido aparente en el marcado puede tener ahora varios elementos secundarios asignados como contenido. A continuación se muestra la sintaxis de contenido para una clase derivada de Panel. Todas las clases derivadas de Panel establecen la propiedad de contenido de XAML en Children, lo que requiere un valor de tipo UIElementCollection.

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Observe que ni el elemento de propiedad para Children ni el elemento para UIElementCollection son necesarios en el marcado. Esta es una característica del diseño de XAML, de forma que los elementos incluidos recursivamente que definen una UI se representan de forma más intuitiva como un árbol de elementos anidados con relaciones inmediatas entre los elementos primarios y secundarios, sin etiquetas de elemento de propiedad u objetos de colección intermedios. De hecho, UIElementCollection no se puede especificar explícitamente en el marcado como un elemento de objeto, por razones de diseño. Dado que su único uso previsto es como una colección implícita, UIElementCollection no expone un constructor público predeterminado y, por lo tanto, no se pueden crear instancias de él como un elemento de objeto.

Mezclar elementos de propiedad y elementos de objeto en un objeto con una propiedad de contenido

La especificación XAML declara que un procesador XAML puede exigir que los elementos de objeto que se utilizan para rellenar la propiedad de contenido de XAML dentro de un elemento de objeto sean contiguos y no se mezclen. Esta restricción contra la mezcla de elementos de propiedad y contenido la aplica los procesadores XAML de WPF.

Puede utilizar un elemento de objeto secundario como el primer marcado inmediato dentro de un elemento de objeto. A continuación, puede introducir elementos de propiedad. O bien, puede especificar uno o varios elementos de propiedad, seguidos del contenido y, por último, más elementos de propiedad. Pero una vez que un elemento de propiedad sigue al contenido, no se podrá introducir ningún otro tipo de contenido, únicamente se podrán agregar elementos de propiedad.

Este requisito de orden de elemento de contenido/propiedad no se aplica al texto interno utilizado como contenido. Sin embargo, mantener el texto interno contiguo es un buen estilo de marcado, ya que el espacio en blanco significativo será difícil de detectar visualmente en el marcado si los elementos de propiedad están intercalados en el texto interno.

Espacios de nombres XAML

En ninguno de los ejemplos de sintaxis anteriores se especificó un espacio de nombres XAML distinto del predeterminado. En las aplicaciones WPF típicas, se especifica el espacio de nombres WPF como espacio de nombres predeterminado de XAML. Puede especificar espacios de nombres XAML distintos del espacio de nombres XAML predeterminado y seguir usando sintaxis similar. Pero luego, en cualquier parte donde se nombre una clase que no sea accesible dentro del espacio de nombres XAML predeterminado, ese nombre de clase debe ir precedida del prefijo del espacio de nombres XAML según se asigna al espacio de nombres CLR correspondiente. Por ejemplo, <custom:Example/> es la sintaxis de elementos de objeto para crear una instancia de la clase Example, donde el espacio de nombres CLR que contiene dicha clase (y posiblemente la información de ensamblado externo que contiene tipos de respaldo) se asignó previamente al prefijo custom.

Para obtener más información sobre los espacios de nombres XAML, vea Espacios de nombres y asignación de espacios de nombres XAML para WPF.

Extensiones de marcado

XAML define una entidad de programación de extensión de marcado que ofrece una vía alternativa al control habitual de valores de atributos de cadena o elementos de objetos del procesador XAML, y cede el procesamiento a una clase de respaldo. El carácter que identifica una extensión de marcado ante un procesador XAML al utilizar la sintaxis de atributo es la llave de la apertura ({), seguida por cualquier carácter distinto de una llave de cierre (}). La primera cadena que sigue a la llave de la apertura debe hacer referencia a la clase que proporciona el comportamiento de la extensión en particular, donde la referencia puede omitir la subcadena "Extensión" si dicha subcadena forma parte del nombre de clase verdadero. A partir de ese momento, puede aparecer un solo espacio, y la implementación de extensión utiliza cada carácter subsiguiente como entrada, hasta que se encuentra la llave de cierre.

La implementación de XAML de .NET utiliza la clase abstracta MarkupExtension como base para todas las extensiones de marcado admitidas por WPF y otros marcos o tecnologías. Las extensiones de marcado que WPF implementa específicamente se diseñan a menudo para proporcionar un medio de hacer referencia a otros objetos ya existentes, o para hacer referencias diferidas a los objetos que se evaluarán en tiempo de ejecución, mientras se utiliza la sintaxis de atributo. Por ejemplo, un enlace de datos simple de WPF se consigue especificando la extensión de marcado {Binding} en lugar del valor que tomaría normalmente una propiedad determinada. Muchas de las extensiones de marcado de WPF permiten la existencia de una sintaxis de atributo para propiedades en las que, de lo contrario, no sería posible una sintaxis de atributo. Por ejemplo, un objeto Style es un tipo relativamente complejo que contiene una serie anidada de objetos y propiedades. Los estilos en WPF se definen normalmente como un recurso en ResourceDictionary y, a continuación, se hace referencia a ellos mediante una de las dos extensiones de marcado que solicitan un recurso. La extensión de marcado cede la evaluación del valor de propiedad a una búsqueda de recursos y habilita el ofrecer el valor de la propiedad Style, tomando el tipo Style, en la sintaxis de atributo del ejemplo siguiente:

<Button Style="{StaticResource MyStyle}">My button</Button>

Aquí, StaticResource identifica la clase StaticResourceExtension que proporciona la implementación de la extensión de marcado. La cadena siguiente, MyStyle, se utiliza como entrada para el constructor StaticResourceExtension no predeterminado, donde el parámetro tal y como se toma de la cadena de extensión declara el objeto ResourceKey solicitado. Se espera que MyStyle sea el valor x:Key de un objeto Style definido como recurso. El uso de Extensión de marcado StaticResource requiere que el recurso se utilice para proporcionar el valor de la propiedad Style mediante una lógica de búsqueda de recursos estáticos en el momento de la carga.

Para obtener más información sobre las extensiones de marcado, vea Extensiones de marcado y XAML de WPF. Para obtener una referencia de extensiones de marcado y otras características de programación de XAML habilitadas en la implementación general de XAML en .NET, vea Características de lenguaje (x:) de espacios de nombres XAML. Para las extensiones de marcado específicas del WPF, vea Extensiones XAML de WPF.

Propiedades asociadas

Las propiedades adjuntas son un concepto de programación introducido en XAML en virtud del cual las propiedades las puede poseer y definir un tipo determinado, pero se pueden establecer como atributos o elementos de propiedad para cualquier elemento. El escenario principal para el que están pensadas las propiedades adjuntas es aquél que permite a los elementos secundarios de una estructura de marcado enviar información a un elemento primario sin necesidad de un modelo de objetos compartido por todos los elementos. Y a la inversa, los elementos primarios pueden utilizar las propiedades asociadas para enviar información a los elementos secundarios. Para obtener más información sobre el propósito de las propiedades asociadas y cómo crear sus propias propiedades asociadas, vea Información general sobre propiedades asociadas.

Las propiedades asociadas utilizan una sintaxis que a primera vista es similar a la de los elementos de propiedad, ya que también se debe especificar una combinación nombreDeTipo.nombreDePropiedad. Hay dos diferencias importantes:

  • Puede utilizar la combinación nombreDeTipo.nombreDePropiedad incluso al establecer una propiedad asociada a través de la sintaxis de atributo. Las propiedades asociadas son el único caso en el que certificar el nombre de la propiedad es un requisito en una sintaxis de atributo.

  • También puede utilizar la sintaxis de elementos de propiedad para las propiedades asociadas. Sin embargo, en la sintaxis de elementos de propiedad típica, el nombreDeTipo especificado es el elemento de objeto que contiene el elemento de propiedad. Si está haciendo referencia a una propiedad asociada, el nombreDeTipo es la clase que define la propiedad asociada, no el elemento de objeto contenedor.

Eventos asociados

Los eventos adjuntos son otro concepto de programación introducido en XAML según el cual un tipo concreto puede definir los eventos, pero los controladores se pueden adjuntar a cualquier elemento de objeto. En la implementación de WOF, a menudo, el tipo que define un evento adjunto es un tipo estático que define un servicio, y algunas veces estos eventos adjuntos están expuestos por un alias de evento enrutado en los tipos que exponen el servicio. Los controladores para los eventos asociados se especifican mediante la sintaxis de atributo. Al igual que sucede con los eventos adjuntos, la sintaxis de atributo se expande para los eventos adjuntos con objeto de permitir el uso de nombreDeTipo.nombreDeEvento, donde nombreDeTipo es la clase que proporciona los descriptores de acceso de controlador de eventos Add y Remove para la infraestructura de evento adjunto, y nombreDeEvento es el nombre del evento.

Anatomía de un elemento raíz XAML

La tabla siguiente muestra el típico elemento raíz XAML desglosado; en ella se aprecian los atributos concretos de un elemento raíz:

<Page

Elemento de objeto de apertura del elemento raíz

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

El espacio de nombres XAML (WPF) predeterminado

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

El espacio de nombres XAML del lenguaje XAML

x:Class="ExampleNamespace.ExampleCode"

La declaración de clase parcial que conecta el marcado con cualquier código subyacente definido en la clase parcial

>

Final del elemento de objeto para la raíz. Todavía no se cierra el objeto porque el elemento contiene elementos secundarios

Usos opcionales y no recomendados de XAML

En las siguientes secciones se describen usos de XAML que son admitidos técnicamente por procesadores de XAML, pero que producen nivel de detalle u otros problemas estéticos que interfieren con los archivos XAML que siguen siendo humanamente legibles cuando desarrolla aplicaciones que contienen orígenes XAML.

Usos opcionales de los elementos de propiedad

Los usos opcionales de los elementos de propiedad incluyen la escritura explícita de las propiedades de contenido de los elementos que el procesador XAML considera implícitas. Por ejemplo, al declarar el contenido de un objeto Menu, podría optar por declarar explícitamente la colección Items del objeto Menu como una etiqueta de elemento de propiedad <Menu.Items>, y situar cada MenuItem dentro de <Menu.Items> en lugar de utilizar el comportamiento implícito del procesador XAML, en el que todos los elementos secundarios de un objeto Menu deben ser valores MenuItem y se sitúan en la colección Items. A veces los usos opcionales pueden ayudar a clarificar visualmente la estructura del objeto tal y como se representa en el marcado. En otras ocasiones, el uso explícito de un elemento de propiedad puede evitar un marcado que es técnicamente funcional pero visualmente confuso, como las extensiones de marcado anidadas dentro de un valor de atributo.

Atributos nombreDeTipo.nombreDeMiembro completos

El formato typeName.memberName para un atributo funciona más universalmente que el caso de evento enrutado. Pero en otras situaciones ese formato es superfluo y se debería evitar, aunque solo fuera por razones de estilo de marcado y legibilidad. En el ejemplo siguiente, cada una de las tres referencias al atributo Background son completamente equivalentes:

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background funciona porque la búsqueda calificada de esa propiedad en el objeto Button se realiza correctamente (Background se ha heredado de Control) y Button es la clase del elemento de objeto o una clase base. Control.Background funciona porque la clase Control define, en realidad, la propiedad Background y Control es una clase base Button.

Sin embargo, en el ejemplo siguiente la forma nombreDeTipo.nombreDeMiembro no funciona y, por tanto, se muestra con formato de comentario:

<!--<Button Label.Background="Blue">Does not work</Button> -->

Label es otra clase derivada de Control, y si hubiese especificado Label.Background dentro de un elemento de objeto Label, este uso habría funcionado. Sin embargo, debido a que Label no es la clase o la clase base de Button, el comportamiento especificado del procesador XAML es procesar Label.Background como una propiedad adjunta. Label.Background no es una propiedad adjunta disponible y se produce un error en este uso.

Elementos de propiedad nombreDeTipoBase.nombreDeMiembro

La sintaxis nombreDeTipoBase.nombreDeMiembro funciona para la sintaxis de elementos de propiedad de manera análoga a como lo hace nombreDeTipo.nombreDeMiembro en la sintaxis de atributos. Por ejemplo, la sintaxis siguiente funciona:

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

Aquí, el elemento de propiedad se ha proporcionado como Control.Background aunque dicho elemento estaba incluido en Button.

Pero al igual que la forma nombreDeTipo.nombreDeMiembro para los atributos, nombreDeTipoBase.nombreDeMiembro denota un estilo pobre en el marcado y debería evitarlo.

Vea también

Conceptos

Información general sobre XAML (WPF)

Información general sobre las propiedades de dependencia

Clases TypeConverter y XAML

Clases XAML y personalizadas para WPF

Otros recursos

Características de lenguaje (x:) de espacios de nombres XAML

Extensiones XAML de WPF