Información general sobre XAML

Actualización: noviembre 2007

En este tema se describen las características del lenguaje Lenguaje de marcado de aplicaciones extensible (XAML) y se muestra cómo utilizar XAML para escribir aplicaciones Windows Presentation Foundation (WPF). En este tema se describe específicamente XAML tal y como lo implementa Windows Presentation Foundation (WPF). El propio XAML es un concepto de lenguaje más amplio que Windows Presentation Foundation (WPF).

Este tema contiene las secciones siguientes.

  • Un lenguaje declarativo compatible con el control de flujo
  • Elementos de objeto XAML
  • Establecer propiedades
  • Valores de referencia y extensiones de marcado
  • Valores de atributo habilitados para el convertidor de tipos
  • Tipos de colección y propiedades de la colección XAML
  • Propiedades del contenido XAML
  • El uso de mayúsculas y minúsculas y del espacio en blanco en XAML
  • Más información sobre la sintaxis XAML
  • Elementos raíz en XAML y espacios de nombres XML
  • Eventos y el código XAML subyacente
  • x:Name
  • Propiedades y eventos asociados
  • Clases base y XAML
  • Seguridad XAML
  • Cargar XAML desde el código
  • Pasos adicionales
  • Temas relacionados

Un lenguaje declarativo compatible con el control de flujo

XAML simplifica la creación de una interfaz de usuario para el modelo de programación de .NET Framework. Puede crear elementos de la interfaz de usuario visibles en el marcado XAML declarativo y, a continuación, separar la definición de la interfaz de usuario de la lógica en tiempo de ejecución utilizando archivos de código subyacente, que se unen al marcado mediante definiciones de clases parciales. La capacidad de combinar código con marcado en XAML es importante porque XML por sí solo es declarativo, y no sugiere realmente un modelo para el control de flujo. Un lenguaje declarativo basado en XML es muy intuitivo para crear interfaces que van desde el prototipo a la producción, sobre todo para las personas con entrenamiento en diseño y tecnologías web. A diferencia de la mayoría de los demás lenguajes de marcado, XAML representa directamente la creación de instancias de objetos administrados. Este principio de diseño general habilita el código simplificado y el acceso a la depuración para los objetos que se crean en XAML.

Los archivos de XAML son archivos de XML que normalmente tienen la extensión .xaml.

El ejemplo de XAML siguiente muestra la pequeña cantidad de marcado necesaria para crear un botón como parte de una interfaz de usuario. El botón creado tiene una presentación visual predeterminada procedente de los estilos del tema y un comportamiento predeterminado procedente de su diseño de clase.

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

Elementos de objeto XAML

XAML tiene un conjunto de reglas que asignan elementos de objeto a clases o estructuras, atributos a propiedades o eventos, y espacios de nombres de XML a espacios de nombres de CLR. Los elementos de XAML se asignan a los tipos de Microsoft .NET tal y como se definen en los ensamblados a los que se hace referencia y los atributos se asignan a los miembros de dichos tipos.

En el ejemplo anterior se han especificado dos elementos de objeto: <StackPanel> (con una etiqueta de cierre) y <Button/> (que también tenía varios atributos; éstos se describen en una sección posterior). Cada una de las cadenas StackPanel y Button se asignan al nombre de una clase definida por WPF y que forma parte de los ensamblados de WPF. Al especificar una etiqueta de elemento de objeto, se crea una instrucción para el procesamiento de XAML que indica que se debe crear una nueva instancia de la clase con nombre al cargar la página XAML. Cada instancia se crea llamando al constructor predeterminado de la clase subyacente o estructura y almacenando el resultado. Para que se pueda utilizar como un elemento de objeto en XAML, dicha clase o estructura debe exponer un constructor público predeterminado (sin parámetros).

Establecer propiedades

Las propiedades en XAML se establecen definiendo propiedades en un elemento de objeto utilizando alguna de las sintaxis posibles. Las sintaxis que se pueden utilizar para una propiedad determinada variarán, dependiendo de las características de la propiedad que se está estableciendo.

Para agregar características a los elementos de objeto, establezca los valores de las propiedades. El estado inicial de la instancia de objeto subyacente para 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 atributo

En XAML, las propiedades se pueden expresar a menudo como atributos. La sintaxis de atributo es la sintaxis de establecimiento de propiedades más optimizada y será la más intuitiva para los programadores que han utilizado lenguajes de marcado en el pasado. Por ejemplo, el marcado siguiente crea un botón que tiene texto rojo y un fondo azul, y también muestra texto especificado como Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Sintaxis de elementos de propiedad

En algunas propiedades de un elemento de objeto, no es posible usar la sintaxis de atributo, ya que el objeto o la información necesaria para proporcionar el valor de la propiedad no se puede expresar correctamente como una cadena simple. En estos casos, se puede utilizar otra sintaxis conocida como sintaxis de elementos de propiedad. La sintaxis de elementos de propiedad establece la propiedad del elemento contenedor a la que se hace referencia en el contenido de la etiqueta. Generalmente, el contenido es un objeto del tipo que la propiedad toma como valor propio (con la instancia del valor normalmente especificada como otro elemento de objeto). La sintaxis para el elemento de propiedad en sí es <nombreDeTipo.Propiedad>. Después de especificar el contenido, se debe cerrar el elemento de propiedad con una etiqueta de cierre como cualquier otro elemento (con la sintaxis </nombreDeTipo.Propiedad>). 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. Si es posible utilizar una sintaxis de atributo, su uso es generalmente más conveniente, ya que habilita un marcado más compacto, pero es simplemente una cuestión de estilo, no una limitación técnica. El ejemplo siguiente muestra cómo se establecen las mismas propiedades que en el ejemplo anterior de sintaxis de atributo, pero ahora utilizando la sintaxis de elementos de propiedad para todas las propiedades de Button.

<Button>
  <Button.Background>
    <SolidColorBrush Color="Blue"/>
  </Button.Background>
  <Button.Foreground>
    <SolidColorBrush Color="Red"/>
  </Button.Foreground>
  <Button.Content>
    This is a button
  </Button.Content>
</Button>

La sintaxis de elementos de propiedad para XAML representa una variación significativa de la interpretación de XML básica del marcado. Para XML, <nombreDeTipo.Propiedad> representa otro elemento, sin ninguna relación necesariamente implícita con un elemento primario TypeName aparte del hecho de ser un elemento secundario. En XAML, <nombreDeTipo.Property> implica directamente que Property es una propiedad de nombreDeTipo, establecida por el contenido del elemento de propiedad, y nunca será un elemento con nombre similar sino un elemento independiente con un punto en el nombre.

Propiedades y herencia de clases

Las propiedades tal y como aparecen como atributos XAML en un elemento de WPF se heredan a menudo de las clases base. Por ejemplo, en el ejemplo anterior, 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 otra desviación significativa de la interpretación de XML básica del marcado. La herencia de clases (especialmente cuando las clases base intermedias son abstractas) 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. Asimismo, la "X" de XAML corresponde a "eXtensible" y la extensibilidad descarta la integridad de cualquier representación dada de "qué es XAML para WPF" (aunque mantener definiciones de espacios de nombres XML independientes puede ayudar a resolver este problema; este concepto se describe en una sección posterior).

Valores de referencia y extensiones de marcado

Las extensiones de marcado son un concepto de XAML. En la sintaxis de atributo, las llaves ({ y }) indican un uso de la extensión de marcado. Este uso hace que el procesamiento de XAML se aparte del tratamiento general de valores de atributo como una cadena literal o un valor directamente convertible en cadena.

Cuando las propiedades toman un valor de tipo de referencia, requerirán a menudo una sintaxis de elementos de propiedad (lo que crea siempre una nueva instancia) o una referencia de objeto mediante una extensión de marcado. El uso de una extensión de marcado puede devolver una instancia existente, por lo que puede ser más versátil o incurrir en una menor sobrecarga de objetos.

Cuando se utiliza una extensión de marcado para proporcionar un valor de atributo, éste debería ser proporcionado por la lógica de la clase de respaldo para la extensión de marcado pertinente. Las extensiones de marcado más comunes utilizadas en la programación de aplicaciones de WPF son Binding, utilizada para las expresiones de enlace de datos, y las referencias de recursos StaticResource y DynamicResource. Las extensiones de marcado permiten utilizar la sintaxis de atributo para proporcionar valores de referencia para las propiedades, aun cuando dichas propiedades no admitan una sintaxis de atributo para la creación de instancias de objeto directas, o permiten habilitar un comportamiento concreto que difiera del comportamiento general que requiere que las propiedades de XAML se rellenen con valores del tipo de la propiedad.

Por ejemplo, en el ejemplo siguiente se establece el valor de la propiedad Style utilizando la sintaxis de atributo. La propiedad Style toma una instancia de la clase Style, un tipo de referencia que de forma predeterminada no se podía especificar dentro de una cadena de sintaxis de atributo. Pero en este caso, el atributo hace referencia a una extensión de marcado determinada, StaticResource. Cuando se procesa dicha extensión de marcado, devuelve una referencia a un estilo del que ya se han creado instancias como un recurso con clave en un diccionario de recursos.

<Page.Resources>
  <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
  <Style TargetType="Border" x:Key="PageBackground">
    <Setter Property="Background" Value="Blue"/>
  </Style>


...


</Page.Resources>
<StackPanel>
  <Border Style="{StaticResource PageBackground}">


...


  </Border>
</StackPanel>

Los recursos son simplemente un uso de las extensiones de marcado habilitado por WPF o XAML. Para obtener una lista de referencias de extensiones de marcado, vea Extensiones de XAML de espacio de nombres de WPF o Características de lenguaje (x:) de espacios de nombres XAML. Para obtener más información sobre las extensiones de marcado, vea Extensiones de marcado y XAML.

Valores de atributo habilitados para el convertidor de tipos

En la sección Sintaxis de atributo, se ha dicho que el valor de atributo debe poder establecerlo una cadena. El control nativo básico de cómo se convierten las cadenas en otros tipos de objetos o valores primitivos está basado en el propio tipo String. Pero muchos tipos de WPF o miembros de esos tipos extienden el comportamiento básico del procesamiento de atributos de cadena, de tal forma que se pueden especificar instancias de tipos de objeto más complejos como valores de atributo mediante una cadena. En el nivel de código, este procesamiento se logra especificando un convertidor de tipos CLR que procesa el valor de atributo de cadena. El tipo de estructura Thickness, utilizado normalmente para indicar mediciones de una área rectangular, como una propiedad Margin, es un ejemplo de tipo que tiene una sintaxis de atributo especial habilitada para el convertidor de tipos expuesta para todas las propiedades que toman dicho tipo, con objeto de proporcionar facilidad de uso en el marcado XAML. En el ejemplo siguiente se utiliza una sintaxis de atributo habilitada para el convertidor de tipos con objeto de proporcionar un valor a la propiedad Margin:

<Button Margin="10,20,10,30" Content="Click me"/>

El ejemplo de sintaxis de atributo anterior es equivalente al ejemplo de sintaxis siguiente más detallado, donde la propiedad Margin se establece mediante la sintaxis de elementos de propiedad que contiene un elemento de objeto Thickness, y se establecen cuatro propiedades clave de Thickness como atributos en la nueva instancia:

<Button Content="Click me">
  <Button.Margin>
    <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
  </Button.Margin>
</Button>

Aunque el uso de la sintaxis habilitada para el convertidor de tipos o de una sintaxis equivalente más detallada es generalmente una opción de estilo de codificación, la primera permite obtener un marcado más optimizado. (Sin embargo, hay un número limitado de objetos en los que el convertidor de tipos es la única manera de establecer una propiedad en ese tipo, debido a que el propio objeto de tipo no tiene un constructor predeterminado. Un ejemplo sería Cursor.)

Para obtener más información sobre la compatibilidad con la sintaxis de atributo habilitada para el convertidor de tipos, vea Clases TypeConverter y XAML.

Tipos de colección y propiedades de la colección XAML

XAML especifica una característica del lenguaje por la que el elemento de objeto que representa un tipo de colección se puede omitir deliberadamente en el marcado. Cuando un procesador de XAML controla una propiedad que toma un tipo de colección, se crea implícitamente una instancia del tipo de colección adecuado, aun cuando el elemento de objeto para dicha colección no esté presente en el marcado. En las páginas de referencia del SDK 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.

La sintaxis de colección implícita está disponible para los tipos que implementan IList o IDictionary, o para las matrices.

Ya ha visto un ejemplo de una sintaxis de colección implícita sin que se llame a ésta, en el ejemplo de recursos de XAML:

<Page.Resources>
  <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
  <Style TargetType="Border" x:Key="PageBackground">
    <Setter Property="Background" Value="Blue"/>
  </Style>


...


</Page.Resources>
<StackPanel>
  <Border Style="{StaticResource PageBackground}">


...


  </Border>
</StackPanel>

Con la excepción del elemento raíz, cada elemento de objeto de una página 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 XAML para el elemento primario (las propiedades de contenido 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. En el caso del ejemplo de los recursos, la propiedad Resources toma un objeto de tipo ResourceDictionary. En el ejemplo siguiente se muestra la sintaxis equivalente con el elemento de objeto para el valor ResourceDictionary especificado explícitamente.

<Page.Resources>
  <ResourceDictionary>
      <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
      <Style TargetType="Border" x:Key="PageBackground">
        <Setter Property="Background" Value="Blue"/>
      </Style>


...


  </ResourceDictionary>
</Page.Resources>
<StackPanel>
  <Border Style="{StaticResource PageBackground}">


...


    </Border>
  </StackPanel>
</Page>

La colección Resources es un ejemplo de una propiedad de colección que está presente en muchos elementos comunes del nivel de marco de trabajo de WPF. Para establecer esta propiedad en XAML es necesaria la sintaxis de elementos de propiedad. Cada elemento de objeto incluido dentro del elemento de propiedad se convierte en un elemento de la colección (una implementación de IDictionary ). Aunque el propio tipo de colección tiene normalmente una propiedad o indizador que contiene los elementos, esa propiedad no se puede especificar en el marcado; es totalmente implícita. Para el objeto ResourceDictionary, la propiedad es el indizador Item.

Para obtener un ejemplo más completo del uso del diccionario de recursos, vea Cómo: Definir y hacer referencia a un recurso.

Propiedades del contenido XAML

XAML especifica una característica del lenguaje por la que cualquier clase que se puede utilizar como un elemento de objeto de XAML puede designar exactamente una de sus propiedades como la propiedad de contenido XAML para las instancias de la clase. Cuando un procesador de XAML controla un elemento de objeto que tiene una propiedad de contenido XAML, los elementos secundarios de XML de dicho elemento de objeto se procesan como si estuvieran contenidos en una etiqueta de elemento de propiedad implícita que representa esa propiedad de contenido. Dentro del marcado, se puede omitir la sintaxis de elementos de propiedad para la propiedad de contenido XAML. Cualquier elemento secundario especificado en el marcado se convertirá en el valor de la propiedad de contenido XAML.

Ya ha visto un ejemplo de una propiedad de contenido XAML sin que se llame a ésta: el primer ejemplo de este tema.

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

Aquí, Button es un elemento secundario de StackPanel. Éste es un marcado optimizado e intuitivo que omite dos etiquetas por dos razones diferentes.

  • Elemento de propiedad StackPanel.Children omitido: StackPanel se deriva de Panel. Panel define Panel.Children como su propiedad de contenido XAML. Por lo tanto, todas las clases derivadas de Panel tienen esa propiedad de contenido XAML y se puede omitir el elemento de propiedad para Panel.Children.

  • Elemento de objeto UIElementCollection omitido: La propiedad Panel.Children toma el tipo UIElementCollection, que implementa IList. Por consiguiente, se puede omitir la etiqueta de elemento de objeto UIElementCollection, basándose en las reglas de XAML definidas para las colecciones. En este caso, no se pueden crear instancias de UIElementCollection como elementos de objeto. Ni siquiera se tiene la opción de declarar explícitamente ese objeto de colección. Esto se debe a que UIElementCollection no expone un constructor predeterminado. Otros tipos de colección de WPF tampoco exponen los constructores para el uso de elementos de objeto, porque el control de la sintaxis de la colección de XAML todavía les permite trabajar implícitamente en XAML. Ésta es la razón por la que el elemento de objeto UIElementCollection se muestra con comentarios en el ejemplo; sin ellos, el ejemplo no se compilaría.

<StackPanel>
  <StackPanel.Children>
    <!--<UIElementCollection>-->
    <Button>
      <Button.Content>
        Click Me
      </Button.Content>
    </Button>
    <!--</UIElementCollection>-->
  </StackPanel.Children>
</StackPanel>

Texto interno y propiedades del contenido XAML

El ejemplo StackPanel / Button todavía tiene otra variante.

<StackPanel>
  <Button>Click Me</Button>
</StackPanel>

Observe el cambio en la forma en la que se especifica el texto de la presentación para Button. La propiedad Content se especificó anteriormente en la sintaxis de atributo; esta vez, la cadena de la presentación es el texto interno que está dentro de un elemento de objeto Button. Esta sintaxis funciona porque Content es la propiedad de contenido XAML de la clase base ContentControl de Button. La cadena incluida en el elemento se evalúa basándose en el tipo de propiedad de la propiedad Content, que es Object. Object no intenta ninguna conversión de tipos de cadenas, por lo que el valor de la propiedad Content se convierte en el valor de cadena literal. Alternativamente, el contenido incluido dentro de Button podría haber sido cualquier Object único. Los controles como Button generalmente definen la propiedad de contenido XAML para la clase de manera que la propiedad de contenido XAML se puede utilizar para la interfaz de usuario y el texto de la presentación, para la composición de controles o para ambos.

La capacidad de colocar las cadenas dentro del elemento como contenido para generar marcado que se parece a otros lenguajes de marcado comunes es de especial importancia para el modelo de documento dinámico (para obtener más información, vea Documentos en Windows Presentation Foundation) y para la localización (vea Globalización para Windows Presentation Foundation).

Los valores de las propiedades de contenido XAML deben ser contiguos

El valor de una propiedad de contenido 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 XAML se especifica como una cadena o como uno o varios objetos. Por ejemplo, el marcado siguiente no se puede compilar:

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

Esto no es válido básicamente porque si esta sintaxis fuera 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>

Modelos de contenido

Una clase podría admitir su uso como un elemento 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. Para algunos controles que tienen modelos de contenido más complejos, el modelo de contenido se documenta como un tema conceptual independiente. Visite Modelos de contenido.

El uso de mayúsculas y minúsculas y del espacio en blanco en XAML

XAML distingue entre mayúsculas y minúsculas. Los elementos de objeto, los elementos de propiedad y los nombres de atributo se deben especificar utilizando la grafía apropiada cuando se comparan por nombre con el tipo subyacente en el ensamblado, o con un miembro de un tipo. Los valores para los atributos no siempre distinguen entre mayúsculas y minúsculas. La distinción entre mayúsculas y minúsculas para los valores dependerá del comportamiento del convertidor de tipos asociado a la propiedad que toma el valor o del tipo de valor de propiedad. Por ejemplo, las propiedades que toma el tipo Boolean pueden tomar true o True como valores equivalentes, pero sólo porque la conversión de tipos de cadena predeterminada para Boolean ya los permite como equivalentes.

Los procesadores y serializadores de XAML omiten o quitan todos los espacios en blanco no significativos y normalizan cualquier espacio en blanco significativo. Este comportamiento generalmente sólo tiene importancia si se especifican cadenas dentro de las propiedades de contenido XAML. Es decir, XAML convierte los caracteres de espacio, avance de línea y tabulación en espacios y, a continuación, conserva un espacio si lo encuentra en cualquier extremo de una cadena contigua. La explicación completa del control de espacios en blanco de XAML no se aborda en este tema. Para obtener información más detallada, vea Procesamiento de espacios en blanco en XAML.

Más información sobre la sintaxis XAML

La sintaxis de colección implícita y las propiedades de contenido XAML son características del lenguaje XAML que habilitan la omisión de ciertas etiquetas deducidas. El objetivo de estas características es conseguir que las relaciones entre los elementos primarios-secundarios de una página sean más claras al crear o examinar el marcado.

Para obtener más información sobre la sintaxis de atributo y la sintaxis de elementos de propiedad, así como sobre otros términos utilizados al describir la sintaxis XAML a lo largo de la documentación del SDK, vea Terminología de la sintaxis de XAML. El tema Terminología de la sintaxis de XAML también es un buen lugar para comenzar si está considerando los usos de XAML que desea habilitar al crear una clase personalizada.

Elementos raíz en XAML y espacios de nombres XML

Para que un archivo XAML pueda ser tanto un archivo XML con un formato correcto como un archivo XAML válido, sólo debe tener un elemento raíz. Normalmente, se debe elegir un elemento que forme parte del modelo de aplicación (por ejemplo, Window o Page para una página, ResourceDictionary para un diccionario externo o Application para la raíz de la definición de la aplicación). En el ejemplo siguiente se muestra el elemento raíz de un archivo XAML típico para una página WPF, con el elemento raíz Page.

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


...


</Page>

El elemento raíz también contiene los atributos xmlns y xmlns:x. Estos atributos indican a un procesador de XAML los espacios de nombres XML que contienen las definiciones de los elementos a los que el marcado hará referencia. El atributo xmlns indica específicamente el espacio de nombres XML predeterminado. Dentro este espacio de nombres XML, los elementos de objeto en el marcado se pueden especificar sin un prefijo. Para la mayoría de los escenarios de aplicaciones de WPF y para casi todos los ejemplos ofrecidos en las secciones de WPF del SDK, el espacio de nombres XML predeterminado está asignado al espacio de nombres https://schemas.microsoft.com/winfx/2006/xaml/presentation de WPF. El atributo xmlns:x indica un espacio de nombres XML adicional, que asigna el espacio de nombres del lenguaje XAML https://schemas.microsoft.com/winfx/2006/xaml. Los componentes del lenguaje necesarios definidos por la especificación XAML tienen el prefijo x: cuando se hace referencia a ellos en el marcado de un archivo con esta asignación. Este uso de xmlns para definir un ámbito de uso y asignación es coherente con la especificación XML 1.0. Tenga en cuenta que los atributos xmlns sólo son estrictamente necesarios en el elemento raíz de cada página y en la definición de aplicación si se proporciona ésta en el marcado. Las definiciones xmlns se aplicarán a todos los elementos secundarios de la raíz (este comportamiento sigue siendo coherente con la especificación XML 1.0 para xmlns). Los atributos xmlns también se permiten en otros elementos por debajo de la raíz y se aplicarían a los elementos secundarios del elemento que los define. Sin embargo, éste no es un uso típico, porque una definición o redefinición frecuente de los espacios de nombres XML puede dar lugar a un estilo de marcado XAML que resulte difícil de leer.

Los ensamblados de WPF se sabe que contienen los tipos que admiten las asignaciones de WPF al espacio de nombres XML predeterminado debido a la configuración que forma parte del archivo de compilación del proyecto. Los ensamblados también se asignan en los archivos .targets. Por lo tanto, únicamente es necesario asignar el xmlns para poder hacer referencia a los elementos de XAML que vienen de los ensamblados de WPF. Para sus propios ensamblados personalizados o para los ensamblados fuera de WPF, puede especificar el ensamblado como parte de la asignación de xmlns. Normalmente, se elige un prefijo diferente, pero también es posible elegir un espacio de nombres XML diferente como valor predeterminado y, a continuación, asignar WPF a un prefijo. Para obtener más información sobre la relación existente entre los espacios de nombres XML y los espacios de nombres del código de respaldo en los ensamblados, vea Espacios de nombres y asignación de espacios de nombres de XAML.

El prefijo x:

En el ejemplo de elemento raíz anterior, se utilizó el prefijo x: para asignar el espacio de nombres XML en XAML https://schemas.microsoft.com/winfx/2006/xaml. Este prefijo x: se utiliza para asignar el espacio de nombres XML en XAML en las plantillas de los proyectos, en los ejemplos y en la documentación de este SDK. El prefijo x: o espacio de nombres XML en XAML contiene varias construcciones de programación que utilizará con frecuencia en el XAML. A continuación se muestra una lista de las construcciones de programación prefijo x: o espacio de nombres en XAML más comunes que utilizará:

  • x:Key: establece una clave única para cada recurso de un elemento ResourceDictionary. x:Key representará probablemente el 90% de los usos de x: que verá en el marcado de su aplicación.

  • x:Class: especifica el espacio de nombres de CLR y el nombre de clase para la clase que proporciona código subyacente para una página XAML. Debe disponer de esta clase para admitir el código subyacente; por esto casi siempre verá x: asignado, aun cuando no haya ningún recurso.

  • x:Name: especifica un nombre de objeto en tiempo de ejecución para la instancia que existe en el código en tiempo de ejecución una vez procesado un elemento de objeto. Utilice x:Name para aquellos casos de asignación de nombres a elementos en los que no se admite la propiedad de nivel de marco de trabajo de WPF Name equivalente. Esto sucede en ciertos escenarios de animación.

  • x:Static: habilita una referencia de valor que obtiene un valor estático que de lo contrario no sería una propiedad compatible con XAML. 

  • x:Type: construye una referencia Type basada en un nombre de tipo. Esto se utiliza para especificar atributos que toman valores Type, como Style.TargetType, aunque en muchos casos la propiedad dispone de una conversión de cadena a Type nativa y el uso de x:Type es opcional.

Hay construcciones de programación adicionales en el prefijo x: o espacio de nombres en XAML que no son tan habituales. Para obtener información más detallada, vea Características de lenguaje (x:) de espacios de nombres XAML.

Eventos y el código XAML subyacente

La mayoría de las aplicaciones de WPF constan de marcado y código subyacente. Dentro de un proyecto, el código XAML se escribe como un archivo .xaml y se utiliza un lenguaje de CLR, como Microsoft Visual Basic .NET o C#, para escribir un archivo de código subyacente. Cuando se compila un archivo XAML, la ubicación del archivo de código XAML subyacente para cada página XAML se identifica especificando un espacio de nombres y una clase como atributo x:Class del elemento raíz de la página XAML.

En los ejemplos presentados hasta ahora se incluían varios botones, pero ninguno de ellos tenía todavía ningún comportamiento lógico asociado. El mecanismo primario en el nivel de la aplicación para agregar un comportamiento a un elemento de objeto consiste en utilizar un evento existente de la clase de elemento y escribir un controlador específico para dicho evento que se invocará cuando se provoque éste en tiempo de ejecución. El nombre del evento y el nombre del controlador que se van a utilizar se especifican en el marcado, mientras que el código que implementa el controlador se define en el código subyacente.

<Page 
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MyNamespace.MyPageCode">
  <Button Click="ClickHandler" >Click Me!</Button>
</Page>
namespace MyNamespace
{
  public partial class MyPageCode
  {
    void ClickHandler(object sender, RoutedEventArgs e)
    {
      Button b = e.Source as Button;
      b.Background = Brushes.Red;
    }
  }
}

Tenga en cuenta que el archivo de código subyacente utiliza el espacio de nombres CLR MyNamespace y declara MyPageCode como una clase parcial dentro de dicho espacio de nombres. Esto es similar al valor de atributo x:Class de MyNamespace.MyPageCode que se ha proporcionado en la raíz del marcado. El compilador creará automáticamente una clase parcial para cualquier página de XAML compilada, derivando una clase del tipo de elemento raíz. Al proporcionar código subyacente que también define la misma clase parcial, el código resultante se combina dentro del mismo espacio de nombres y la clase de la aplicación compilada.

Para obtener más información sobre los requisitos para la programación de código subyacente, vea la sección "Requisitos del código subyacente, los controladores de eventos y las clases parciales" de Código subyacente y XAML.

Si no desea crear un archivo de código subyacente independiente, también puede insertar el código dentro de un archivo XAML. Sin embargo, el código insertado es una técnica menos versátil que tiene importantes limitaciones. Para obtener información más detallada, vea Código subyacente y XAML.

Sintaxis de atributo de evento

Al especificar el comportamiento mediante eventos en el marcado, se utiliza normalmente la sintaxis de atributo para asociar los controladores. El elemento de objeto donde se especifica el atributo de evento se convierte en la instancia que escucha el evento y llama al controlador. El nombre del evento concreto que desea controlar es el nombre del atributo. El valor del atributo es el nombre de método del controlador que se definirá. A continuación, debe proporcionar la implementación del controlador en el código subyacente, controlador que estará basado en el delegado para ese evento. El controlador se escribe en código subyacente en un lenguaje de programación como Microsoft Visual Basic .NET o C#.

Cada evento de WPF proporcionará datos de evento cuando éste se produzca. Los controladores de eventos pueden tener acceso a estos datos de evento. En el ejemplo anterior, el controlador obtiene el origen de evento del que se informa a través de los datos de evento y, a continuación, establece las propiedades en dicho origen.

Eventos enrutados

Una característica especial de los eventos determinada que es única y fundamental para WPF es un evento enrutado. Los eventos enrutados permiten a un elemento controlar un evento producido por otro elemento diferente, siempre que dichos elementos se relacionen entre sí a través de un árbol de elementos. Al especificar el control de eventos con un atributo XAML, se puede escuchar y controlar el evento enrutado en cualquier elemento, incluidos los elementos que no contienen ese evento en particular en la tabla de miembros de clase. Esto se consigue calificando el atributo de nombre de evento con el nombre de la clase propietaria. Por ejemplo, el elemento primario StackPanel en el ejemplo de StackPanel / Button actual podría registrar un controlador para el evento de botón Click del elemento secundario especificando el atributo Button.Click en el elemento de objeto StackPanel, con el nombre del controlador como valor de atributo. Para obtener más información, consulte Información general sobre eventos enrutados.

x:Name

De forma predeterminada, la instancia de objeto que se crea al procesar un elemento de objeto no posee un identificador único o una referencia de objeto inherente que se pueda utilizar en el código. Si se llama a un constructor en el código, casi siempre se utiliza el resultado del constructor para establecer una variable en la instancia creada con objeto de que se pueda hacer referencia a dicha instancia posteriormente en el código. Para proporcionar acceso normalizado a los objetos creados mediante una definición de marcado, XAML define el atributo x:Name. Es posible establecer el valor del atributo x:Name en cualquier elemento de objeto. En el código subyacente, el identificador elegido es equivalente a una variable de instancia que hace referencia a la instancia creada. Los elementos con nombre funcionan en todos los sentidos como si fueran instancias de objeto (el nombre hace referencia a la instancia) y el código subyacente puede hacer referencia a dichos elementos para controlar las interacciones en tiempo de ejecución dentro de la aplicación.

Los elementos del nivel de marco de trabajo de WPF XAML heredan una propiedad Name, que es equivalente al atributo x:Name definido en XAML. Otros tipos de clases también proporcionan equivalentes en el nivel de propiedad para x:Name, que en general también suele definirse como una propiedad Name. En general, si no puede localizar una propiedad Name en la tabla de miembros del elemento elegido, utilice en su lugar x:Name.

En el ejemplo siguiente se establece Name en un elemento StackPanel. A continuación, un controlador en un elemento Button dentro de StackPanel hace referencia al objeto StackPanel mediante su referencia de instancia buttonContainer tal y como lo establece Name.

<StackPanel Name="buttonContainer">


...


  <Button Click="RemoveThis">Click to remove this button</Button>
</StackPanel>
void RemoveThis(object sender, RoutedEventArgs e)
{
    FrameworkElement fe = e.Source as FrameworkElement;
    if (buttonContainer.Children.Contains(fe))
    {
        buttonContainer.Children.Remove(fe);
    }
}

Al igual que una variable, el nombre de una instancia está regido por un concepto de ámbito con objeto de aplicar los nombres de forma que sean únicos dentro de un cierto ámbito predecible. El marcado primario que define una página indica un ámbito de nombres único, siendo el límite de dicho ámbito el elemento raíz de dicha página. Sin embargo, otros orígenes de marcado pueden interactuar con una página en tiempo de ejecución, como los estilos o las plantillas incluidas dentro de los estilos, y dichos orígenes tienen a menudo su propio ámbito de nombres que no tiene por qué estar conectado necesariamente con el de la página. Para obtener más información sobre x:Name y los ámbitos de nombres, vea Name, Atributo x:Name o Ámbitos de nombres de WPF.

Propiedades y eventos asociados

XAML incluye una característica de lenguaje que permite especificar ciertas propiedades o eventos en cualquier elemento, independientemente de si la propiedad o el elemento existe en la tabla de miembros para el elemento en el que se establece. La versión de esta característica para las propiedades se denomina propiedad asociada y la versión para los eventos se denomina evento asociado. Conceptualmente, las propiedades y los eventos asociados se pueden considerar como miembros globales que se pueden establecer en cualquier elemento o clase, independientemente de su jerarquía de clases.

Las propiedades asociadas en XAML se utilizan normalmente mediante la sintaxis de atributo. En la sintaxis de atributo, una propiedad asociada se especifica en la forma tipoDePropietario.nombreDePropiedad. A primera vista, esto se parece al uso de un elemento de propiedad, pero en este caso el tipoDePropietario que se especifica es siempre un tipo distinto del elemento de objeto en el que se establece la propiedad asociada. tipoDePropietario es el tipo que proporciona los métodos de descriptor de acceso que un procesador de XAML requiere para poder obtener o establecer el valor de la propiedad asociada. El escenario más común para las propiedades asociadas es permitir a los elementos secundarios enviar un valor de propiedad a su elemento primario.

En el ejemplo siguiente se muestra la propiedad asociada DockPanel.Dock. La clase DockPanel define los descriptores de acceso para DockPanel.Dock y, por lo tanto, es la propietaria de la propiedad asociada. La clase DockPanel también incluye la lógica que recorre en iteración sus elementos secundarios y busca en cada uno de ellos un valor establecido de DockPanel.Dock. Si se encuentra dicho valor, éste se utiliza durante el diseño para colocar los elementos secundarios. El uso de la propiedad asociada DockPanel.Dock y esta función de posición constituyen de hecho el escenario de motivación para la clase DockPanel.

<DockPanel>
  <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
  <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

En Windows Presentation Foundation (WPF), todas las propiedades asociadas se implementan también como propiedades de dependencia. Para obtener información más detallada, vea Información general sobre propiedades asociadas.

Los eventos asociados utilizan una forma de sintaxis de atributo similar: tipoDePropietario.nombreDeEvento. Al igual que en los eventos no asociados, el valor del atributo para un evento asociado en XAML especifica el nombre del método controlador que se invoca cuando se controla el evento en el elemento. 

Un escenario en el que se utilizan eventos asociados lo constituyen los eventos de entrada de dispositivo que se pueden controlar en cualquier elemento, como los botones del mouse. Un ejemplo de este tipo de evento asociado es Mouse.MouseDown. Sin embargo, la mayoría de los elementos del nivel de marco de trabajo de WPF pueden utilizar este evento sin recurrir a un evento asociado. Esto es debido a que la clase del elemento base UIElement crea un alias para el evento asociado Mouse.MouseDown y expone dicho alias en la tabla de miembros UIElement (como MouseDown). Como resultado, normalmente no es necesario especificar la sintaxis de eventos asociados en una página XAML o en la programación de aplicaciones de Windows Presentation Foundation (WPF). La excepción la constituye el uso de elementos personalizados o elementos de objeto que no se derivan de UIElement, pero que aun así tienen una representación visual (éstos son poco frecuentes). En WPF, todos los eventos asociados se implementan también como eventos enrutados. ContentElement también expone los alias para los eventos de entrada, con objeto de que los utilice el modelo de documento dinámico. Para obtener más información, vea Información general sobre eventos enrutados y Información general sobre acciones del usuario.

Anatomía del elemento raíz de una página XAML

La tabla siguiente muestra el típico elemento raíz de una página XAML desglosado; en ella se aprecian los atributos concretos de un elemento raíz identificados en este tema:

<Page

Elemento de objeto de apertura del elemento raíz

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

El espacio de nombres (WPF) predeterminado

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

El espacio de nombres XAML

x:Class="MyNamespace.MyPageCode"

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

>

Fin del elemento de objeto para la raíz, que aún no se ha cerrado porque la página contiene elementos secundarios

Clases base y XAML

Debajo de XAML y sus esquemas existe una colección de clases que corresponden a los objetos de CLR, así como elementos de marcado que se van a utilizar en XAML. Sin embargo, no todas las clases se pueden asignar a elementos. Las clases abstractas, como ButtonBase, y ciertas clases base no abstractas se utilizan para la herencia en el modelo de objetos CLR y no admiten las etiquetas de marcado XAML correspondientes. Las clases base, incluso las abstractas, son importantes para el desarrollo en XAML porque cada uno de los elementos de XAML concretos hereda miembros de alguna clase base en su jerarquía. A menudo, estos miembros incluyen propiedades que se pueden establecer como atributos en el elemento o eventos que se pueden controlar. FrameworkElement es la clase base concreta de la interfaz de usuario de WPF en el nivel de marco WPF. Al diseñar la interfaz de usuario, se utilizarán varias clases de forma, de panel, de decorador o de control, que se derivan de FrameworkElement. Una clase base relacionada, FrameworkContentElement, admite elementos orientados a documentos que funcionan bien para una presentación de diseño de flujo, utilizando API que reflejan deliberadamente las API de FrameworkElement. La combinación de atributos en el nivel de elemento y un modelo de objetos CLR proporciona un conjunto de propiedades comunes que se pueden establecer en la mayoría de los elementos de XAML concretos, independientemente del tipo de elemento exacto y su clase subyacente.

Seguridad XAML

XAML es un lenguaje de marcado que representa directamente la creación de instancias y la ejecución de objetos. Por consiguiente, los elementos creados en XAML tienen la misma capacidad de interactuar con los recursos del sistema (por ejemplo, el acceso a la red y la E/S del sistema de archivos) que el código generado equivalente.

WPF admite el marco de trabajo de seguridad Seguridad de acceso a código (CAS) de .NET. Esto significa que el contenido de WPF que se ejecuta en la zona de Internet tiene permisos de ejecución reducidos. El "XAML dinámico" (páginas de XAML no compilado interpretadas en el momento de la carga por un visor de XAML) y las Aplicación del explorador XAML (XBAP) se ejecutan normalmente en esta zona de Internet y utilizan el mismo conjunto de permisos. Sin embargo, el XAML que se carga en una aplicación de plena confianza tiene el mismo acceso a los recursos del sistema que la aplicación host. Para obtener más información, consulte Seguridad de confianza parcial en Windows Presentation Foundation.

Cargar XAML desde el código

Se puede utilizar XAML para definir una interfaz de usuario completa, pero a veces también es conveniente definir sólo una parte de dicha interfaz en XAML. Esta función se podría utilizar para habilitar una personalización parcial, para el almacenamiento local de información, utilizando XAML para proporcionar un objeto comercial, o para diversos escenarios posibles. La clave para estos escenarios es la clase XamlReader y su método Load. La entrada es un archivo XAML y el resultado es un objeto que representa el árbol de objetos en tiempo de ejecución completo que se ha creado a partir de ese marcado. A continuación, se puede insertar el objeto como una propiedad de otro objeto que ya existe en la aplicación. Siempre que la propiedad sea una propiedad adecuada en el modelo de contenido que tiene funciones de presentación y que notifique al motor de ejecución que se ha agregado el nuevo contenido a la aplicación, es posible modificar con bastante facilidad el contenido de una aplicación en ejecución cargando XAML. Tenga en cuenta que esta función normalmente sólo está disponible en las aplicaciones de plena confianza, debido a las implicaciones de seguridad obvias de la carga de archivos en aplicaciones que se están ejecutando.

Pasos adicionales

En este tema se proporciona una introducción básica a la terminología y los conceptos de sintaxis de XAML. Para obtener más información sobre los términos utilizados aquí, vea Terminología de la sintaxis de XAML.

Si aún no lo ha hecho, consulte el tutorial Información general sobre Windows Presentation Foundation. La aplicación de marcado descrita en el tutorial le ayudará a reforzar muchos de los conceptos descritos en este tema.

WPF utiliza un modelo de aplicación determinado que está basado en la clase Application. Para obtener información más detallada, vea Información general sobre la administración de aplicaciones.

Generar una aplicación de WPF (WPF) le ofrece más detalles sobre cómo generar aplicaciones XAML inclusivas desde la línea de comandos y con Microsoft Visual Studio.

Información general sobre las propiedades de dependencia le ofrece más información sobre la versatilidad de las propiedades en Windows Presentation Foundation (WPF), e introduce el concepto de propiedades de dependencia.

Por último, en el SDK se incluye una herramienta de edición de XAML denominada XAMLPad. Puede utilizar esta herramienta para realizar pruebas en tiempo real con XAML.

Vea también

Conceptos

XAMLPad

XAML y clases personalizadas

Información general sobre elementos base

Árboles en WPF

Otros recursos

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

Extensiones de XAML de espacio de nombres de WPF

Modelos de contenido