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.
Las extensiones de marcado son una técnica de XAML para obtener un valor que no sea ni un primitivo ni un tipo específico de XAML. Para el uso de atributos, las extensiones de marcado usan la secuencia de caracteres conocida de una llave de apertura { para escribir el ámbito de la extensión de marcado y una llave de cierre } para salir. Cuando use los Servicios XAML de .NET Framework, puede utilizar algunas de las extensiones de marcado del lenguaje XAML predefinidas del ensamblado System.Xaml. También puede crear subclases de la clase MarkupExtension, definida en System.Xaml, y definir sus propias extensiones de marcado. O bien, puede usar las extensiones de marcado definidas por un marco determinado si ya ha hecho referencia a ese marco.
Cuando se obtiene acceso a un uso de la extensión de marcado, el escritor de objetos XAML puede proporcionar los servicios a una clase MarkupExtension personalizada a través de un punto de conexión del servicio en la invalidación de MarkupExtension.ProvideValue. Los servicios se pueden usar para obtener el contexto sobre el uso, las capacidades concretas del escritor de objetos, el contexto de esquema XAML, etc.
Este tema contiene las secciones siguientes.
- Extensiones de marcado definidas por XAML
- La clase base MarkupExtension
- Definición del tipo compatible para una extensión de marcado personalizada
- Modelos de constructor y argumentos posicionales para una extensión de marcado personalizada
- Argumentos con nombre para una extensión de marcado personalizada
- Obtener acceso al contexto de proveedor de servicios desde una implementación de extensión de marcado
- Uso de los elementos de propiedad de una extensión de marcado
- Atribución para una extensión de marcado personalizada
- Serialización de los usos de la extensión de marcado
- Extensiones de marcado en el flujo de nodo XAML
- Temas relacionados
Extensiones de marcado definidas por XAML
Los Servicios XAML de .NET Framework implementan varias extensiones de marcado para la compatibilidad del lenguaje XAML. Estas extensiones de marcado corresponden a las partes de la especificación de XAML como lenguaje. Son típicamente identificables por el prefijo x: en la sintaxis, como se ve en el uso común. Todas las implementaciones de estos elementos de lenguaje XAML por parte de los Servicios XAML de .NET Framework se derivan de la clase base MarkupExtension.
![]() |
---|
El prefijo x: se utiliza para la asignación típica del espacio de nombres XAML del lenguaje XAML, en el elemento raíz de XAML en producción.Por ejemplo, las plantillas de proyecto y página de Visual Studio para diversos marcos concretos inician un archivo XAML mediante esta asignación de x:.Podría elegir un token de prefijo diferente en su propia asignación del espacio de nombres XAML, pero en esta documentación se supone la asignación de x: predeterminada como medio para identificar esas entidades que forman una parte definida del espacio de nombres XAML del lenguaje XAML, para diferenciarlas del espacio de nombres XAML predeterminado de un marco concreto o de otros espacios de nombres CLR o XML arbitrarios. |
x:Type
x:Type proporciona el objeto Type para el tipo nombrado. Esta funcionalidad se usa con mayor frecuencia en los mecanismos de aplazamiento que utilizan un tipo CLR subyacente y la derivación de tipos como un moniker o identificador de agrupamiento. Los estilos y plantillas WPF y su uso de las propiedades de TargetType son un ejemplo concreto. Para obtener más información, vea x:Type (Extensión de marcado).
x:Static
x:Static genera valores estáticos a partir de entidades de código de tipo valor que no son directamente el tipo del valor de una propiedad, pero se pueden evaluar como ese tipo. Esto es útil para especificar los valores que ya existen como constantes conocidas en una definición de tipo. Para obtener más información, vea Extensiones de marcado x:Static.
x:Null
x:Null especifica null como valor para un miembro de XAML. Dependiendo del diseño de tipos específicos o de los conceptos de marco más amplios, null no es siempre un valor predeterminado para una propiedad o el valor implícito de un atributo de cadena vacía. Para obtener más información, vea x:Null (Extensión de marcado).
x:Array
x:Array admite la creación de matrices generales en la sintaxis de XAML, en aquellos casos donde la compatibilidad de colección proporcionado por los elementos base y los modelos de control no se utilicen deliberadamente. Para obtener más información, vea x:Array (Extensión de marcado). En XAML 2009 específicamente, las matrices se obtiene acceso como primitivas del lenguaje en lugar de como extensión. Para obtener más información, vea Características del lenguaje XAML 2009.
x:Reference
x:Reference forma parte de XAML 2009, una extensión del conjunto original del lenguaje (2006). x:Reference representa una referencia a otro objeto existente en un gráfico de objeto. Este objeto se identifica mediante su x:Name. Para obtener más información, vea x:Reference (extensión de marcado).
Otras estructuras x:
Existen otras construcciones x: para admitir las características del lenguaje XAML, pero no se implementan como extensiones de marcado. Para obtener más información, vea Características de lenguaje (x:) de espacios de nombres XAML.
La clase base MarkupExtension
Para definir una extensión de marcado personalizada que puede interactuar con las implementaciones predeterminadas de los lectores y escritores de XAML en System.Xaml, derive una clase de la clase abstracta MarkupExtension. Esa clase tiene un método que se va a invalidar, que es ProvideValue. También podría ser necesario definir los constructores adicionales con el fin de admitir los argumentos para el uso de la extensión de marcado y las propiedades configurables correspondientes.
A través de ProvideValue, una extensión de marcado personalizada obtiene acceso a un contexto de servicio que notifica el entorno donde un procesador XAML invoca realmente la extensión de marcado. En la ruta de acceso de carga, es normalmente XamlObjectWriter. En la ruta de acceso de guardar, es normalmente XamlXmlWriter. Cada uno de ellos notifica el contexto del servicio como una clase de contexto de proveedor de servicios XAML interna que implementa un modelo del proveedor de servicios. Para obtener más información sobre los servicios disponibles y lo que representan, vea Convertidores de tipos y extensiones de marcado para XAML.
Su clase de extensión de marcado debe usar un nivel del acceso público; los procesadores XAML siempre deben poder crear instancias de la clase de soporte de la extensión de marcado para utilizar sus servicios.
Definición del tipo compatible para una extensión de marcado personalizada
Al utilizar los Servicios XAML de .NET Framework o los marcos compilados en los Servicios XAML de .NET Framework, hay dos opciones para denominar el tipo de soporte de la extensión de marcado. El nombre de tipo es pertinente para la forma en que los sistemas de escritura de objetos XAML intentan obtener acceso a un tipo de soporte de extensión de marcado e invocarla cuando encuentran un uso de la extensión de marcado en XAML. Utilice una de las estrategias de nomenclatura siguientes:
Denomine el tipo de manera que sea una coincidencia exacta para el token de uso del marcado XAML. Por ejemplo, para admitir el uso de una extensión {Collate ...}, denomine el tipo de soporte Collate.
Denomine el tipo de manera que sea el token de cadena de uso más la Extension del sufijo. Por ejemplo, para admitir el uso de una extensión {Collate ...}, denomine el tipo de soporte CollateExtension.
El orden de búsqueda comienza en el nombre de clase con el sufijo Extension, después sigue con el nombre de clase sin el sufijo Extension.
Desde la perspectiva de uso del marcado, es válido incluir el sufijo Extension como parte del uso. Sin embargo, esto se comporta como si Extension formara parte realmente del nombre de clase, y los sistemas de escritura de objetos XAML no podrían resolver una clase de soporte de la extensión de marcado para ese uso si la clase de soporte no tuviera el sufijo Extension.
El constructor predeterminado
Para todos los tipos de soporte de extensión de marcado, debería exponer un constructor predeterminado público. Se requiere un constructor predeterminado para los casos en los que un sistema de escritura de objetos XAML cree una instancia de la extensión de marcado a partir del uso de elementos de objeto. Admitir el uso de elementos de objeto es una expectativa justa para una extensión de marcado, en especial para la serialización. Sin embargo, puede implementar una extensión de marcado sin un constructor público si sólo piensa admitir usos de atributo de la extensión de marcado.
Si su uso de la extensión de marcado no tiene ningún argumento, es necesario que el constructor predeterminado admita el uso.
Modelos de constructor y argumentos posicionales para una extensión de marcado personalizada
Para una extensión de marcado con uso de argumento intencional, los constructores públicos deben corresponder a los modos del uso intencional. En otras palabras, si su extensión de marcado está diseñada para requerir un argumento posicional como un uso válido, debería admitir un constructor público con un parámetro de entrada que toma el argumento posicional.
Por ejemplo, suponga que la extensión de marcado Collate está pensada para admitir solo un modo donde hay un argumento posicional que representa su modo, especificado como una constante de enumeración CollationMode. En este caso, debería haber un constructor con el siguiente formato:
public Collate(CollationMode collationMode) {...}
En un nivel básico, los argumentos pasados a una extensión de marcado son una cadena porque se reenvían desde los valores de atributo del marcado. Puede convertir todos sus argumentos en cadenas y trabajar con entradas en ese nivel. Sin embargo, tiene acceso a cierto procesamiento que ocurre antes de que los argumentos de extensión de marcado se pasen a la clase de soporte.
El procesamiento funciona conceptualmente como si la extensión de marcado fuera un objeto que se va a crear y, a continuación, se van a establecer sus valores miembro. Cada propiedad especificada para establecer se evalúa de forma similar a cómo se puede establecer un miembro especificado en un objeto creado cuando se analiza XAML. Hay dos diferencias importantes:
Tal y como se observó anteriormente, un tipo de soporte de extensión de marcado no necesita tener un constructor predeterminado para que se creen instancias del mismo en XAML. Su construcción de objeto se difiere hasta que se crean los tokens de sus posibles argumentos en la sintaxis de texto y se evalúan como argumentos con nombre o posicionales, y se llama al constructor adecuado en ese momento.
Los usos de las extensiones de marcado se pueden anidar. Primero se evalúa la extensión de marcado más interna. Por tanto, se puede suponer este tipo de uso y declarar uno de los parámetros de construcción para que sea un tipo que requiera para la producción un convertidor de valores (como una extensión de marcado).
En el ejemplo anterior se mostraba una confianza en tal procesamiento. El sistema de escritura de objetos XAML de los Servicios XAML de .NET Framework procesa los nombres de constantes de la enumeración en los valores enumerados en un nivel nativo.
El procesamiento de la sintaxis de texto de un parámetro posicional de la extensión de marcado también puede confiar en un convertidor de tipos asociado al tipo que está en el argumento de construcción.
Los argumentos se denominan argumentos posicionales porque el orden en el que se encuentran los tokens en el uso corresponde al orden posicional del parámetro de constructor al que están asignados. Por ejemplo, considere la siguiente firma de constructor:
public Collate(CollationMode collationMode, object collateThis) {...}
Un procesador de XAML espera dos argumentos posicionales para esta extensión de marcado. Si se produjo un uso {Collate AlphaUp,{x:Reference circularFile}}, el token AlphaUp se envía al primer parámetro y se evalúa como constante con nombre de la enumeración CollationMode. El resultado del x:Reference interno se envía al segundo parámetro y se evalúa como un objeto.
En las reglas especificadas en XAML para la sintaxis y el procesamiento de la extensión de marcado, la coma es el delimitador entre los argumentos, ya sean argumentos posicionales o argumentos con nombre.
Aridad duplicada de argumentos posicionales
Si un sistema de escritura de objetos XAML encuentra un uso de la extensión de marcado con argumentos posicionales y hay varios argumentos de constructor que toman ese número de argumentos (una aridad duplicada), no se produce necesariamente un error. El comportamiento depende de un valor de contexto de esquema XAML personalizable, SupportMarkupExtensionsWithDuplicateArity. Si SupportMarkupExtensionsWithDuplicateArity es true, un sistema de escritura de objetos XAML no debería producir una excepción solo por razones de aridad duplicada. El comportamiento después de ese punto no se define estrictamente. La hipótesis de diseño básica es que el contexto del esquema tiene información de tipos disponible para los parámetros concretos y puede intentar conversiones de tipos explícitas que coinciden con los candidatos duplicados para ver qué firma podría ser la mejor coincidencia. Todavía podría producirse una excepción si ninguna de las firmas supera las pruebas impuestas por ese contexto de esquema concreto que se ejecuta en un sistema de escritura de objetos XAML.
De forma predeterminada, SupportMarkupExtensionsWithDuplicateArity es false en el objeto XamlSchemaContext basado en CLR para los Servicios XAML de .NET Framework. Por consiguiente, el objeto XamlObjectWriter predeterminado produce excepciones si encuentra un uso de la extensión de marcado donde hay aridad duplicada en los constructores del tipo de respaldo.
Argumentos con nombre para una extensión de marcado personalizada
Las extensiones de marcado tal y como las especifica XAML también pueden usar un formulario de argumentos con nombre para el uso. En el primer nivel de tokenización, la sintaxis de texto está dividida en argumentos. La presencia de un signo igual (=) dentro de cualquier argumento identifica un argumento como un argumento con nombre. Este tipo de argumento también se convierte en un par de nombre-valor con tokens. El nombre en este caso denomina una propiedad pública configurable del tipo de soporte de la extensión de marcado. Si piensa admitir el uso del argumento con nombre, debería proporcionar estas propiedades públicas configurables. Las propiedades pueden ser heredadas siempre y cuando sigan siendo públicas.
Obtener acceso al contexto de proveedor de servicios desde una implementación de extensión de marcado
Los servicios disponibles son los mismos para cualquier convertidor de valores. La diferencia radica en cómo cada convertidor de valores recibe el contexto del servicio. El acceso a los servicios y los servicios disponibles se documentan en el tema Convertidores de tipos y extensiones de marcado para XAML.
Uso de los elementos de propiedad de una extensión de marcado
Los escenarios para los usos de la extensión de marcado a menudo se diseñan en torno al uso de la extensión de marcado en el uso de atributos. Sin embargo, también es potencialmente posible definir la clase de respaldo para admitir el uso de elementos de propiedad.
Para admitir el uso de elementos de propiedad de su extensión de marcado, defina un constructor predeterminado público. Este no debería ser un constructor de instancias ni un constructor estático. Se requiere esto porque un procesador de XAML generalmente debe invocar al constructor predeterminado en cualquier elemento de objeto que procesa desde el marcado y esto incluye las clases de extensión de marcado como elementos de objeto. Para escenarios avanzados, puede definir rutas de acceso de construcción no predeterminadas para las clases. (Para obtener más información, vea x:FactoryMethod (Directiva)). Sin embargo, no debería utilizar estos modelos con fines de extensión de marcado, porque dificultaría la detección del modelo de uso, tanto para los diseñadores como para los usuarios de marcado sin formato.
Atribución para una extensión de marcado personalizada
Para admitir entornos de diseño y ciertos escenarios del sistema de escritura de objetos XAML, debería atribuir un tipo de soporte de extensión de marcado con varios atributos CLR. Estos atributos notifican el uso de la extensión de marcado intencional.
MarkupExtensionReturnTypeAttribute notifica la información de Type para el tipo de objeto que ProvideValue devuelve. Por su pura firma, ProvideValue devuelve Object. Pero varios consumidores podrían desear una información del tipo de valor devuelto más precisa. Esto incluye:
Diseñadores e IDE, que podrían ser capaces de proporcionar la compatibilidad de conocimiento de tipo para los usos de extensión de marcado.
Implementaciones avanzadas de los controladores SetMarkupExtension en las clases de destino, que podrían confiar en la reflexión para determinar el tipo de valor devuelto de una extensión de marcado en lugar de crear una bifurcación en implementaciones de MarkupExtension conocidas y concretas por nombre.
Serialización de los usos de la extensión de marcado
Cuando un escritor de objetos XAML procesa un uso de extensión de marcado y llama a ProvideValue, el contexto de cuando fue un uso de extensión de marcado persiste en el flujo de nodo XAML pero no en el gráfico de objeto. En el gráfico de objeto, sólo se conserva el valor. Si tiene escenarios de diseño u otras razones para conservar el uso original de la extensión de marcado en el resultado serializado, debe diseñar su propia infraestructura para realizar el seguimiento de los usos de la extensión de marcado desde el flujo de nodo XAML de la ruta de acceso de carga. Puede implementar el comportamiento necesario para volver a crear los elementos del flujo de nodo a partir de la ruta de acceso de carga y volver a reproducirlos en los escritores de XAML para la serialización en la ruta de acceso de guardar, sustituyendo el valor en la posición adecuada del flujo de nodo.
Extensiones de marcado en el flujo de nodo XAML
Si está trabajando con un flujo de nodo XAML en la ruta de acceso de carga, un uso de la extensión de marcado aparece en el flujo de nodo como un objeto.
Si el uso de la extensión de marcado utiliza argumentos posicionales, se representa como un objeto de inicio con un valor de inicialización. Como una representación aproximada del texto, el flujo de nodo se parece al siguiente:
StartObject (XamlType es el tipo de definición de la extensión de marcado, no su tipo de valor devuelto)
StartMember (el nombre de XamlMember es _InitializationText)
Value (los argumentos posicionales son el valor como una cadena que incluye los delimitadores intermedios)
EndMember
EndObject
Un uso de la extensión de marcado con argumentos con nombre se representa como un objeto con los miembros de los nombres pertinentes, cada uno establecido con los valores de cadena de texto.
Al invocar realmente la implementación de ProvideValue de una extensión de marcado, se requiere el contexto de esquema XAML porque requiere la asignación de tipos y la creación de una instancia del tipo de soporte de extensión de marcado. Esta es una razón por la que los usos de la extensión de marcado se conservan de esta manera en los flujos de nodos de los Servicios XAML de .NET Framework: la parte del lector de una ruta de acceso de carga a menudo no tiene el contexto de esquema XAML necesario disponible.
Si está trabajando con un flujo de nodo XAML en la ruta de acceso de guardar, generalmente no existe nada en una representación de gráfico de objeto que pueda informarle de que el uso de la extensión de marcado proporcionó originalmente el objeto que se iba a serializar y un resultado ProvideValue. Los escenarios que necesitan conservar los usos de la extensión de marcado para las acciones de ida y vuelta, al mismo tiempo que capturan otros cambios en el gráfico de objeto, se deben inventar sus propias técnicas para conservar el conocimiento de un uso de la extensión de marcado de la entrada XAML original. Por ejemplo, para restaurar los usos de la extensión de marcado, puede ser necesario trabajar con el flujo de nodo en la ruta de acceso de guardar para restaurar los usos de la extensión de marcado o realizar algún tipo de combinación entre el XAML original y el XAML de ida y vuelta. Algunos marcos que implementan XAML, como WPF, usan tipos intermedios (expresiones) para ayudar a representar los casos donde los usos de la extensión de marcado proporcionaron los valores.
Vea también
Referencia
Conceptos
Extensiones de marcado y XAML de WPF