Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
XAML tal como se implementa en marcos de Common Language Runtime (CLR) admite la capacidad de definir una clase o estructura personalizada en cualquier lenguaje de Common Language Runtime (CLR) y, a continuación, acceder a esa clase mediante marcado XAML. Puedes usar una combinación de tipos definidos por Windows Presentation Foundation (WPF) y tus tipos personalizados dentro del mismo archivo de marcado, normalmente asignando los tipos personalizados a un prefijo de espacio de nombres XAML. En este tema se describen los requisitos que una clase personalizada debe satisfacer para poder usarse como elemento XAML.
Clases personalizadas en aplicaciones o ensamblados
Las clases personalizadas que se usan en XAML se pueden definir de dos maneras distintas: dentro del código subyacente u otro código que genera la aplicación principal de Windows Presentation Foundation (WPF), o como una clase en un ensamblado independiente, como un archivo ejecutable o DLL que se usa como una biblioteca de clases. Cada uno de estos enfoques tiene ventajas y desventajas particulares.
La ventaja de crear una biblioteca de clases es que cualquier clase personalizada de este tipo se puede compartir entre muchas aplicaciones posibles diferentes. Una biblioteca independiente también facilita el control de los problemas de control de versiones de las aplicaciones y simplifica la creación de una clase en la que el uso de la clase previsto es como elemento raíz en una página XAML.
La ventaja de definir las clases personalizadas en la aplicación es que esta técnica es relativamente ligera y minimiza los problemas de implementación y pruebas detectados al introducir ensamblados independientes más allá del ejecutable principal de la aplicación.
Tanto si se definen en el mismo ensamblado como en un ensamblado diferente, las clases personalizadas deben asignarse entre el espacio de nombres CLR y el espacio de nombres XML para poder usarse en XAML como elementos. Consulta Espacios de nombres XAML y Asignación de espacios de nombres para XAML de WPF.
Requisitos de una clase personalizada como elemento XAML
Para poder instanciarse como elemento de objeto, su clase debe cumplir los siguientes requisitos:
La clase personalizada debe ser pública y admitir un constructor público predeterminado (sin parámetros). (Consulte la sección siguiente para obtener notas sobre las estructuras).
La clase personalizada no debe ser una clase anidada. Las clases anidadas y el "punto" en su sintaxis general de uso de CLR interfieren con otras características de WPF o XAML, como las propiedades adjuntas.
Además de habilitar la sintaxis del elemento de objeto, la definición de objeto también habilita la sintaxis de elemento de propiedad para cualquier otra propiedad pública que tome ese objeto como tipo de valor. Esto se debe a que el objeto ahora puede ser instanciado como un elemento de objeto y puede rellenar el valor del elemento de dicha propiedad.
Estructuras
Las estructuras que definas como tipos personalizados siempre pueden construirse en XAML en WPF. Esto se debe a que los compiladores CLR crean implícitamente un constructor sin parámetros para una estructura que inicializa todos los valores de propiedad en sus valores predeterminados. En algunos casos, el comportamiento de construcción predeterminado o el uso de elementos de objeto para una estructura no es deseable. Esto puede deberse a que la estructura está pensada para rellenar valores y funcionar conceptualmente como una unión, donde los valores contenidos podrían tener interpretaciones mutuamente excluyentes y, por tanto, ninguna de sus propiedades se puede establecer. Un ejemplo de WPF de dicha estructura es GridLength. Por lo general, estas estructuras deben implementar un convertidor de tipos de forma que los valores se puedan expresar en forma de atributo, mediante convenciones de cadena que crean las diferentes interpretaciones o modos de los valores de la estructura. La estructura también debe exponer un comportamiento similar para la construcción de código a través de un constructor sin parámetros.
Requisitos para las propiedades de una clase personalizada como atributos XAML
Las propiedades deben hacer referencia a un tipo por valor (como un primitivo) o usar una clase para el tipo que tenga un constructor sin parámetros o un convertidor de tipos dedicado al que pueda tener acceso un procesador XAML. En la implementación de XAML de CLR, los procesadores XAML encuentran estos convertidores mediante el soporte nativo para los primitivos del lenguaje, o mediante la aplicación de TypeConverterAttribute a un tipo o miembro en las definiciones de los tipos de respaldo.
Como alternativa, la propiedad puede hacer referencia a un tipo de clase abstracta o a una interfaz. En el caso de las clases o interfaces abstractas, la expectativa para el análisis de XAML es que el valor de la propiedad debe rellenarse con instancias de clase concretas que implementan la interfaz o instancias de tipos que derivan de la clase abstracta.
Las propiedades se pueden declarar en una clase abstracta, pero solo se pueden establecer en clases concretas que derivan de la clase abstracta. Esto se debe a que la creación del elemento de objeto para la clase requiere un constructor público sin parámetros en la clase .
Sintaxis de atributos activada para TypeConverter
Si proporciona un convertidor de tipos dedicado con atributos en el nivel de clase, la conversión de tipos aplicada habilita la sintaxis de atributo para cualquier propiedad que necesite crear una instancia de ese tipo. Un convertidor de tipos no habilita el uso de elementos de objeto del tipo; solo la presencia de un constructor sin parámetros para ese tipo permite el uso de elementos de objeto. Por lo tanto, las propiedades que están habilitadas para el convertidor de tipos generalmente no se pueden usar en la sintaxis de propiedades, a menos que el propio tipo también admita la sintaxis del elemento de objeto. La excepción a esto es que se puede especificar una sintaxis de elemento de propiedad, pero que dicho elemento contenga una cadena. Ese uso es esencialmente equivalente a un uso de sintaxis de atributo, y este uso no es común a menos que haya una necesidad de un control de espacio en blanco más sólido del valor del atributo. Por ejemplo, el siguiente es un uso de elemento de propiedad que toma una cadena, así como su equivalente en uso de atributo:
<Button>Hallo!
<Button.Language>
de-DE
</Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>
Ejemplos de propiedades en las cuales la sintaxis de atributo está permitida, pero la sintaxis de elemento de propiedad que contiene un elemento de objeto está prohibida a través de XAML, son varias propiedades que aceptan el tipo Cursor. La Cursor clase tiene un convertidor CursorConverterde tipos dedicado, pero no expone un constructor sin parámetros, por lo que la Cursor propiedad solo se puede establecer a través de la sintaxis de atributo aunque el tipo real Cursor sea un tipo de referencia.
Convertidores de tipos de Per-Property
Como alternativa, la propia propiedad puede declarar, en el nivel de propiedad, un convertidor de tipos. Esto permite un "mini idioma" que crea instancias de objetos del tipo de la propiedad insertada, mediante el procesamiento de valores de cadena entrantes del atributo como entrada para una ConvertFrom operación basada en el tipo adecuado. Normalmente, esto se hace para proporcionar un accesorio de conveniencia y no como único medio para permitir la configuración de una propiedad en XAML. Sin embargo, también es posible usar convertidores de tipos para atributos en los que quiera usar tipos CLR existentes que no proporcionen un constructor sin parámetros o un convertidor de tipos con atributos. Algunos ejemplos de la API de WPF son ciertas propiedades que toman el tipo CultureInfo. En este caso, WPF usó el tipo de Microsoft .NET Framework CultureInfo existente para abordar mejor los escenarios de compatibilidad y migración que se usaron en versiones anteriores de marcos, pero el CultureInfo tipo no admitía los constructores necesarios o la conversión de tipos de nivel de tipo para que se pueda usar directamente como un valor de propiedad XAML.
Siempre que expongas una propiedad que tenga un uso xaml, especialmente si eres un autor de control, debes considerar fuertemente la posibilidad de respaldar esa propiedad con una propiedad de dependencia. Esto es especialmente cierto si usas la implementación existente de Windows Presentation Foundation (WPF) del procesador XAML, ya que puedes mejorar el rendimiento utilizando DependencyProperty respaldo. Una propiedad de dependencia expondrá las características del sistema de propiedades que los usuarios esperan de una propiedad accesible en XAML. Esto incluye características como animación, enlace de datos y compatibilidad con estilos. Para obtener más información, consulta Propiedades de dependencia personalizadas y Carga xaml y Propiedades de dependencia.
Escritura y asignación de un convertidor de tipos
En ocasiones, tendrá que escribir una clase derivada personalizada TypeConverter para proporcionar la conversión de tipos para el tipo de propiedad. Para obtener instrucciones sobre cómo derivar y crear un convertidor de tipos que admita usos XAML, y cómo aplicar TypeConverterAttribute, consulta TypeConverters y XAML.
Requisitos para la sintaxis del atributo controlador de eventos XAML en los eventos de una clase personalizada
Para poder usarse como evento CLR, el evento debe exponerse como un evento público en una clase que admita un constructor sin parámetros o en una clase abstracta a la que se pueda tener acceso al evento en clases derivadas. Para poder usarse convenientemente como evento enrutado, el evento CLR debe implementar métodos add
y remove
explícitos, para agregar y quitar controladores para la firma de eventos CLR y reenviar esos controladores a los métodos AddHandler y RemoveHandler. Estos métodos agregan o quitan los controladores al almacén del controlador de eventos enrutado en la instancia a la que está asociado el evento.
Nota:
Es posible registrar controladores directamente para eventos enrutados mediante AddHandlery no definir deliberadamente un evento CLR que exponga el evento enrutado. Esto no suele recomendarse porque el evento no habilitará la sintaxis de atributo XAML para adjuntar controladores y la clase resultante ofrecerá una vista XAML menos transparente de las funcionalidades de ese tipo.
Escribir propiedades de colección
Las propiedades que toman un tipo de colección tienen una sintaxis XAML que permite especificar objetos que se agregan a la colección. Esta sintaxis tiene dos características importantes.
No es necesario especificar el objeto de colección en la sintaxis del elemento de objeto. La presencia de ese tipo de colección es implícita siempre que se especifica una propiedad en XAML que toma un tipo de colección.
Los elementos secundarios de la propiedad de colección en el marcado se procesan para convertirse en miembros de la colección. Normalmente, el acceso de código a los miembros de una colección se realiza a través de métodos list/dictionary como
Add
, o a través de un indexador. Pero la sintaxis XAML no admite métodos ni indexadores (excepción: XAML 2009 puede admitir métodos, pero el uso de XAML 2009 restringe los posibles usos de WPF; consulta Características del lenguaje XAML 2009). Obviamente, las colecciones son un requisito muy común para crear un árbol de elementos y necesitas alguna manera de rellenar estas colecciones en XAML declarativo. Por lo tanto, los elementos secundarios de una propiedad de colección se procesan añadiéndolos a la colección correspondiente al tipo de propiedad de colección.
La implementación de los servicios XAML de .NET Framework y, por tanto, el procesador XAML de WPF usa la siguiente definición para lo que constituye una propiedad de colección. El tipo de propiedad de la propiedad debe implementar uno de los siguientes:
Implementa IList.
Implementa IDictionary.
Deriva de Array (para obtener más información sobre las matrices en XAML, consulta x:Array Markup Extension).)
IAddChild, implementa una interfaz definida por WPF.
Cada uno de estos tipos en CLR tiene un Add
método, que usa el procesador XAML para agregar elementos a la colección subyacente al crear el gráfico de objetos.
Nota:
El procesador XAML de WPF no admite la detección de colecciones en interfaces genéricas (List
y Dictionary
) y (IList<T> y IDictionary<TKey,TValue>). Sin embargo, puede usar la List<T> clase como una clase base, ya que implementa IList directamente o Dictionary<TKey,TValue> como una clase base, ya que implementa IDictionary directamente.
Al declarar una propiedad que toma una colección, tenga cuidado sobre cómo se inicializa ese valor de propiedad en nuevas instancias del tipo. Si no va a implementar la propiedad como una propiedad de dependencia, es adecuado que la propiedad utilice un campo de respaldo que llama al constructor del tipo de colección. Si la propiedad es una propiedad de dependencia, es posible que deba inicializar la propiedad de colección como parte del constructor de tipo predeterminado. Esto se debe a que una propiedad de dependencia toma su valor predeterminado de los metadatos y normalmente no quiere que el valor inicial de una propiedad de colección sea una colección estática compartida. Debe haber una instancia de colección por cada instancia de tipo contenedor. Para obtener más información, consulte Propiedades de dependencia personalizadas.
Puede implementar un tipo de colección personalizado para la propiedad de tu colección. Debido al tratamiento implícito de propiedades de colección, el tipo de colección personalizado no necesita proporcionar un constructor sin parámetros para poder usarse implícitamente en XAML. Sin embargo, opcionalmente, puede proporcionar un constructor sin parámetros para el tipo de colección. Esto puede ser una práctica útil. A menos que proporcione un constructor sin parámetros, no se puede declarar explícitamente la colección como un elemento de objeto. Es posible que algunos autores de marcado prefieran ver la colección explícita como cuestión de estilo de marcado. Además, un constructor sin parámetros puede simplificar los requisitos de inicialización al crear nuevos objetos que usen el tipo de colección como valor de propiedad.
Declarar propiedades de contenido XAML
El lenguaje XAML define el concepto de una propiedad de contenido XAML. Cada clase que se puede usar en la sintaxis de objeto puede tener exactamente una propiedad de contenido XAML. Para declarar una propiedad como la propiedad de contenido XAML de tu clase, aplica el ContentPropertyAttribute como parte de la definición de la clase. Especifique el nombre de la propiedad de contenido XAML prevista como el atributo Name. La propiedad se especifica como una cadena por nombre, no como una construcción de reflexión como PropertyInfo.
Puedes especificar una propiedad de colección para que sea la propiedad de contenido XAML. Esto da como resultado un uso de esa propiedad en la que el elemento de objeto puede tener uno o varios elementos secundarios, sin elementos de objeto de colección ni etiquetas de elemento de propiedad que intervengan. Estos elementos se tratan como el valor de la propiedad de contenido XAML y se agregan a la instancia de la colección de respaldo.
Algunas propiedades de contenido XAML existentes usan el tipo de propiedad de Object
. Esto habilita una propiedad de contenido XAML que puede tomar valores primitivos como , String así como tomar un valor de objeto de referencia único. Si sigue este modelo, su tipo es responsable de la determinación de tipos, así como del manejo de tipos posibles. La razón habitual de un Object tipo de contenido es admitir un medio simple de agregar contenido de objeto como una cadena (que recibe un tratamiento de presentación predeterminado) o un medio avanzado de agregar contenido de objeto que especifica una presentación no predeterminada o datos adicionales.
Serialización de XAML
En ciertos escenarios, como si eres un autor de control, también querrás asegurarte de que cualquier representación de objeto que se pueda instanciar en XAML también se pueda serializar de nuevo a un marcado de XAML equivalente. Los requisitos de serialización no se describen en este tema. Consulte Información general sobre la creación de controles y árbol de elementos y serialización.
Consulte también
.NET Desktop feedback