Extensiones de marcado y XAML de WPFMarkup Extensions and WPF XAML

En este tema se presenta el concepto de extensiones de marcado para XAML, incluidos sus reglas de sintaxis, su finalidad y el modelo de objeto de clase subyacente.This topic introduces the concept of markup extensions for XAML, including their syntax rules, purpose, and the class object model that underlies them. Las extensiones de marcado son una característica general del lenguaje XAML y de la implementación .NET de servicios XAML.Markup extensions are a general feature of the XAML language and of the .NET implementation of XAML services. En este tema se detallan las extensiones de marcado para su uso en XAML de WPF.This topic specifically details markup extensions for use in WPF XAML.

Procesadores XAML y extensiones de marcadoXAML Processors and Markup Extensions

Por lo general, un analizador de XAML puede interpretar un valor de atributo como una cadena literal que se puede convertir a un primitivo o convertir a un objeto de algún modo.Generally speaking, a XAML parser can either interpret an attribute value as a literal string that can be converted to a primitive, or convert it to an object by some means. Uno de estos modos es haciendo referencia a un convertidor de tipos: se documenta en el tema Clases TypeConverter y XAML.One such means is by referencing a type converter; this is documented in the topic TypeConverters and XAML. Sin embargo, hay escenarios donde se necesita un comportamiento diferente.However, there are scenarios where different behavior is required. Por ejemplo, un procesador XAML puede recibir la orden de que un valor de un atributo no debería producir un nuevo objeto en el gráfico de objetos.For example, a XAML processor can be instructed that a value of an attribute should not result in a new object in the object graph. En su lugar, el atributo debería producir un gráfico de objeto que hiciera referencia a un objeto ya construido en otra parte del gráfico o un objeto estático.Instead, the attribute should result in an object graph that makes a reference to an already constructed object in another part of the graph, or a static object. Otro escenario es que un procesador XAML puede recibir una orden para usar una sintaxis que proporciona argumentos no predeterminados al constructor de un objeto.Another scenario is that a XAML processor can be instructed to use a syntax that provides non-default arguments to the constructor of an object. Estos son los tipos de escenario donde una extensión de marcado puede proporcionar la solución.These are the types of scenarios where a markup extension can provide the solution.

Sintaxis de extensiones de marcado básicaBasic Markup Extension Syntax

Una extensión de marcado se puede implementar para proporcionar valores a propiedades en un uso de atributos, a propiedades en un uso de elementos de propiedad o ambos usos.A markup extension can be implemented to provide values for properties in an attribute usage, properties in a property element usage, or both.

Cuando se usa para proporcionar un valor de atributo, la sintaxis que distingue una secuencia de extensión de marcado para un procesador XAML es la presencia de llaves de apertura y cierre ({ y }).When used to provide an attribute value, the syntax that distinguishes a markup extension sequence to a XAML processor is the presence of the opening and closing curly braces ({ and }). A continuación, el token de cadena inmediatamente posterior a la llave de apertura identifica el tipo de extensión de marcado.The type of markup extension is then identified by the string token immediately following the opening curly brace.

Cuando se usa en la sintaxis de elemento de propiedad, una extensión de marcado es visualmente igual que cualquier otro elemento que se use para proporcionar un valor de elemento de propiedad: una declaración de elemento XAML que hace referencia a la clase de extensión de marcado como un elemento, incluido entre corchetes angulares (<>).When used in property element syntax, a markup extension is visually the same as any other element used to provide a property element value: a XAML element declaration that references the markup extension class as an element, enclosed within angle brackets (<>).

Extensiones de marcado definidas por XAMLXAML-Defined Markup Extensions

Existen varias extensiones de marcado que no son específicas de la implementación de WPF de XAML, pero que son implementaciones intrínsecas o características de XAML como lenguaje.Several markup extensions exist that are not specific to the WPF implementation of XAML, but are instead implementations of intrinsics or features of XAML as a language. Estas extensiones de marcado se implementan en el ensamblado System.Xaml como parte de los servicios XAML de .NET Framework generales y están dentro del espacio de nombres XAML del lenguaje XAML.These markup extensions are implemented in the System.Xaml assembly as part of the general .NET Framework XAML services, and are within the XAML language XAML namespace. En cuanto al uso de marcación común, estas extensiones de marcado se suelen identificar por el prefijo x: en el uso.In terms of common markup usage, these markup extensions are typically identifiable by the x: prefix in the usage. La clase base MarkupExtension (también definida en System. xaml) proporciona el patrón que deben usar todas las extensiones de marcado para que se admita en lectores XAML y escritores de XAML, incluido en XAML de WPF.The MarkupExtension base class (also defined in System.Xaml) provides the pattern that all markup extensions should use in order to be supported in XAML readers and XAML writers, including in WPF XAML.

  • x:Type proporciona el objeto Type para el tipo con nombre.x:Type supplies the Type object for the named type. Esta función se usa con más frecuencia en estilos y plantillas.This facility is used most frequently in styles and templates. Para obtener más información, consulte x:Type (Extensión de marcado).For details, see x:Type Markup Extension.

  • x:Static genera valores estáticos.x:Static produces static values. Los valores proceden de entidades de código de tipo de valor que no son directamente el tipo del valor de una propiedad de destino, pero que se pueden evaluar como ese tipo.The values come from value-type code entities that are not directly the type of a target property's value, but can be evaluated to that type. Para obtener más información, consulte Extensiones de marcado x:Static.For details, see x:Static Markup Extension.

  • x:Null especifica null como un valor para una propiedad y se puede usar para atributos o valores de elemento de propiedad.x:Null specifies null as a value for a property and can be used either for attributes or property element values. Para obtener más información, consulte x:Null (Extensión de marcado).For details, see x:Null Markup Extension.

  • x:Array admite la creación de matrices generales en sintaxis XAML para casos en los que no se use deliberadamente el soporte de colección que proporcionan los elementos base y los modelos de control.x:Array provides support for creation of general arrays in XAML syntax, for cases where the collection support provided by WPF base elements and control models is deliberately not used. Para obtener más información, consulte x:Array (Extensión de marcado).For details, see x:Array Markup Extension.

Nota

El prefijo x: se usa para la asignación de espacio de nombres típica de XAML para los objetos intrínsecos del lenguaje XAML, en el elemento raíz de una producción o un archivo XAML.The x: prefix is used for the typical XAML namespace mapping of the XAML language intrinsics, in the root element of a XAML file or production. Por ejemplo, las plantillas de Visual Studio para aplicaciones de WPF inician un archivo XAML usando esta asignación de x:.For example, the Visual Studio templates for WPF applications initiate a XAML file using this x: mapping. Puede elegir un token de prefijo diferente en su propia asignación de espacio de nombres XAML, pero en esta documentación se presupone la asignación x: predeterminada como manera de identificar las entidades que forman una parte definida del espacio de nombres XAML del lenguaje XAML, en lugar de un espacio de nombres predeterminado de WPF o de otros espacios de nombres XAML que no estén relacionados con ningún marco específico.You could choose a different prefix token in your own XAML namespace mapping, but this documentation will assume the default x: mapping as a means of identifying those entities that are a defined part of the XAML namespace for the XAML language, as opposed to the WPF default namespace or other XAML namespaces not related to a specific framework.

Extensiones de marcado específicas de WPFWPF-Specific Markup Extensions

Las extensiones de marcado más comunes que se usan en la programación de WPF son las que admiten referencias de recursos (StaticResource y DynamicResource) y las que admiten el enlace de datos (Binding).The most common markup extensions used in WPF programming are those that support resource references (StaticResource and DynamicResource), and those that support data binding (Binding).

  • StaticResource proporciona un valor para una propiedad sustituyendo el valor de un recurso ya definido.StaticResource provides a value for a property by substituting the value of an already defined resource. Finalmente, se realiza una evaluación StaticResource en tiempo de carga XAML y no tiene acceso al gráfico de objetos en tiempo de ejecución.A StaticResource evaluation is ultimately made at XAML load time and does not have access to the object graph at run time. Para obtener más información, consulte Extensión de marcado StaticResource.For details, see StaticResource Markup Extension.

  • DynamicResource proporciona un valor para una propiedad aplazando ese valor para que sea una referencia a un recurso en tiempo de ejecución.DynamicResource provides a value for a property by deferring that value to be a run-time reference to a resource. Una referencia de recurso dinámico fuerza una nueva búsqueda cada vez que se tiene acceso a este tipo de recurso y tiene acceso al gráfico de objetos en tiempo de ejecución.A dynamic resource reference forces a new lookup each time that such a resource is accessed and has access to the object graph at run time. Para obtener este acceso, las propiedades de dependencia del sistema de propiedades de WPF y las expresiones evaluadas admiten el concepto DynamicResource.In order to get this access, DynamicResource concept is supported by dependency properties in the WPF property system, and evaluated expressions. Por lo tanto, solo puede usar DynamicResource para un destino de propiedad de dependencia.Therefore you can only use DynamicResource for a dependency property target. Para obtener más información, consulte Extensión de marcado DynamicResource.For details, see DynamicResource Markup Extension.

  • Binding proporciona un valor enlazado a datos para una propiedad mediante el contexto de datos que se aplica al objeto primario en tiempo de ejecución.Binding provides a data bound value for a property, using the data context that applies to the parent object at run time. Esta extensión de marcado es relativamente compleja, porque permite una sintaxis insertada sustancial para especificar un enlace de datos.This markup extension is relatively complex, because it enables a substantial inline syntax for specifying a data binding. Para obtener más información, consulte Binding (extensión de marcado).For details, see Binding Markup Extension.

  • RelativeSource proporciona información de origen para una Binding que puede navegar por varias posibles relaciones en el árbol de objetos en tiempo de ejecución.RelativeSource provides source information for a Binding that can navigate several possible relationships in the run-time object tree. Esto proporciona un origen especializado para los enlaces que se crean en plantillas de uso múltiple o creados en código sin conocimiento completo del árbol de objetos adyacente.This provides specialized sourcing for bindings that are created in multi-use templates or created in code without full knowledge of the surrounding object tree. Para obtener más información, consulte Extensión de marcado RelativeSource.For details, see RelativeSource MarkupExtension.

  • TemplateBinding permite que una plantilla de control use valores para propiedades con plantilla procedentes de propiedades definidas por el modelo de objeto de la clase que usará la plantilla.TemplateBinding enables a control template to use values for templated properties that come from object-model-defined properties of the class that will use the template. En otras palabras, la propiedad dentro de la definición de plantilla puede obtener acceso a un contexto que solo existe cuando se aplica la plantilla.In other words, the property within the template definition can access a context that only exists once the template is applied. Para obtener más información, consulte Extensión de marcado TemplateBinding.For details, see TemplateBinding Markup Extension. Para obtener más información sobre el uso práctico de TemplateBinding, consulte Aplicación de estilos con el ejemplo ControlTemplates.For more information on the practical use of TemplateBinding, see Styling with ControlTemplates Sample.

  • ColorConvertedBitmap admite un escenario de creación de imágenes relativamente avanzado.ColorConvertedBitmap supports a relatively advanced imaging scenario. Para obtener más información, consulte ColorConvertedBitmap (extensión de marcado).For details, see ColorConvertedBitmap Markup Extension.

  • ComponentResourceKey y ThemeDictionary admiten aspectos de búsqueda de recursos, especialmente para recursos y temas que se empaquetan con controles personalizados.ComponentResourceKey and ThemeDictionary support aspects of resource lookup, particularly for resources and themes that are packaged with custom controls. Para obtener más información, consulte Extensión de marcado ComponentResourceKey, Extensión de marcado ThemeDictionary o Información general sobre la creación de controles.For more information, see ComponentResourceKey Markup Extension, ThemeDictionary Markup Extension, or Control Authoring Overview.

Clases de extensión de **Extension Classes

Tanto para el lenguaje XAML general como para las extensiones de marcado específicas de WPF, el comportamiento de cada extensión de marcado se identifica como un procesador XAML a través de una clase *Extension que se deriva de MarkupExtensiony proporciona una implementación del método ProvideValue.For both the general XAML language and WPF-specific markup extensions, the behavior of each markup extension is identified to a XAML processor through a *Extension class that derives from MarkupExtension, and provides an implementation of the ProvideValue method. Este método de cada extensión proporciona el objeto que se devuelve cuando se evalúa la extensión de marcado.This method on each extension provides the object that is returned when the markup extension is evaluated. El objeto devuelto se suele evaluar según los distintos token de cadena que se pasan a la extensión de marcado.The returned object is typically evaluated based on the various string tokens that are passed to the markup extension.

Por ejemplo, la clase StaticResourceExtension proporciona la implementación de la superficie de la búsqueda de recursos real para que su implementación de ProvideValue devuelva el objeto que se solicita, con la entrada de esa implementación concreta como una cadena que se usa para buscar el recurso por su x:Key.For example, the StaticResourceExtension class provides the surface implementation of actual resource lookup so that its ProvideValue implementation returns the object that is requested, with the input of that particular implementation being a string that is used to look up the resource by its x:Key. Gran parte de este detalle de implementación no es importante si usa una extensión de marcado existente.Much of this implementation detail is unimportant if you are using an existing markup extension.

Algunas extensiones de marcado no usan argumentos de token de cadena.Some markup extensions do not use string token arguments. Esto es porque devuelven un valor estático o coherente o porque el contexto para el valor que se debe devolver está disponible mediante uno de los servicios que se pasan con el parámetro serviceProvider.This is either because they return a static or consistent value, or because context for what value should be returned is available through one of the services passed through the serviceProvider parameter.

El patrón de nomenclatura *Extension es por comodidad y coherencia.The *Extension naming pattern is for convenience and consistency. No es necesario para que un procesador XAML identifique esa clase como compatible para una extensión de marcado.It is not necessary in order for a XAML processor to identify that class as support for a markup extension. Siempre que el código base incluya System. XAML y use .NET Framework implementaciones de servicios XAML, todo lo que se necesita para que se reconozca como una extensión de marcado XAML es derivar de MarkupExtension y admitir una sintaxis de construcción.So long as your codebase includes System.Xaml and uses .NET Framework XAML Services implementations, all that is necessary to be recognized as a XAML markup extension is to derive from MarkupExtension and to support a construction syntax. WPF define las clases de habilitación de la extensión de marcado que no siguen el patrón de nomenclatura *Extension, por ejemplo Binding.WPF defines markup extension-enabling classes that do not follow the *Extension naming pattern, for example Binding. Normalmente, el motivo es que la clase admite escenarios más allá de la compatibilidad de extensión de marcado pura.Typically the reason for this is that the class supports scenarios beyond pure markup extension support. En el caso de Binding, esa clase admite el acceso en tiempo de ejecución a los métodos y propiedades del objeto para los escenarios que no tienen nada que hacer con XAML.In the case of Binding, that class supports run-time access to methods and properties of the object for scenarios that have nothing to do with XAML.

Interpretación de la clase de extensión del texto de inicializaciónExtension Class Interpretation of Initialization Text

Un procesador XAML interpreta los token de cadena que siguen el nombre de la extensión de marcado y están dentro de las llaves de las siguientes maneras:The string tokens following the markup extension name and still within the braces are interpreted by a XAML processor in one of the following ways:

  • Una coma siempre representa el separador o el delimitador de token individuales.A comma always represents the separator or delimiter of individual tokens.

  • Si los token separados individuales no contienen ningún signo igual, cada token se trata como un argumento constructor.If the individual separated tokens do not contain any equals signs, each token is treated as a constructor argument. Cada parámetro constructor debe proporcionarse como el tipo que espera la signatura y en el orden apropiado que espera la signatura.Each constructor parameter must be given as the type expected by that signature, and in the proper order expected by that signature.

    Nota

    Un procesador XAML debe llamar al constructor que coincida con el recuento de argumentos del número de pares.A XAML processor must call the constructor that matches the argument count of the number of pairs. Por esta razón, si está implementando una extensión de marcado personalizada, no proporcione varios constructores con el mismo recuento de argumentos.For this reason, if you are implementing a custom markup extension, do not provide multiple constructors with the same argument count. El comportamiento de cómo se comporta un procesador XAML si existe más de una ruta de acceso de constructor de extensión de marcado con el mismo recuento de parámetros no está definido, pero debe prever que un procesador XAML puede producir una excepción en el uso si esta situación se da en las definiciones de tipo de las extensiones de marcado.The behavior for how a XAML processor behaves if more than one markup extension constructor path with the same parameter count exists is not defined, but you should anticipate that a XAML processor is permitted to throw an exception on usage if this situation exists in the markup extension type definitions.

  • Si los tokens separados individuales contienen signos de igual, un procesador XAML llama primero al constructor sin parámetros para la extensión de marcado.If the individual separated tokens contain equals signs, then a XAML processor first calls the parameterless constructor for the markup extension. A continuación, cada par nombre=valor se interpreta como un nombre de propiedad que existe en la extensión de marcado y un valor que se asigna a esa propiedad.Then, each name=value pair is interpreted as a property name that exists on the markup extension, and a value to assign to that property.

  • Si hay un resultado paralelo entre el comportamiento del constructor y el comportamiento de la configuración de propiedades en una extensión de marcado, no importa qué comportamiento use.If there is a parallel result between the constructor behavior and the property setting behavior in a markup extension, it does not matter which behavior you use. Es más común usar los pares propiedad=valor pares para las extensiones de marcado que tienen más de una propiedad configurable, aunque solamente sea porque hace que la marcación sea más calculada y es menos probable transponer accidentalmente parámetros constructor.It is more common usage to use the property=value pairs for markup extensions that have more than one settable property, if only because it makes your markup more intentional and you are less likely to accidentally transpose constructor parameters. (Cuando se especifican pares propiedad = valor, esas propiedades pueden estar en cualquier orden). Además, no hay ninguna garantía de que una extensión de marcado suministre un parámetro de constructor que establezca cada una de sus propiedades configurables.(When you specify property=value pairs, those properties may be in any order.) Also, there is no guarantee that a markup extension supplies a constructor parameter that sets every one of its settable properties. Por ejemplo, Binding es una extensión de marcado, con muchas propiedades que se pueden establecer a través de la extensión en el formato de valor de propiedad=, pero Binding solo admite dos constructores: un constructor sin parámetros y otro que establece un valor de tipo Ruta de acceso inicial.For example, Binding is a markup extension, with many properties that are settable through the extension in property=value form, but Binding only supports two constructors: a parameterless constructor, and one that sets an initial path.

  • Una coma literal no se puede pasar a una extensión de marcado sin escape.A literal comma cannot be passed to a markup extension without escapement.

Secuencias de escape y extensiones de marcadoEscape Sequences and Markup Extensions

El control de atributos en un procesador XAML usa las llaves como indicadores de una secuencia de extensión de marcado.Attribute handling in a XAML processor uses the curly braces as indicators of a markup extension sequence. También es posible generar un valor de atributo de caracteres literales de llave si es necesario, escribiendo una secuencia de escape con un par de llaves vacío seguido de la llave de cierre literal.It is also possible to produce a literal curly brace character attribute value if necessary, by entering an escape sequence using an empty curly brace pair followed by the literal curly brace. Vea {} extensión de marcado de secuencia de escape.See {} Escape Sequence - Markup Extension.

Anidar extensiones de marcado en uso de XAMLNesting Markup Extensions in XAML Usage

Se admite el anidamiento de varias extensiones de marcado. Se empezará a evaluar las extensiones de marcado por profundidad.Nesting of multiple markup extensions is supported, and each markup extension will be evaluated deepest first. Por ejemplo, considere el siguiente uso:For example, consider the following usage:

<Setter Property="Background"  
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />  

En este uso, la instrucción x:Static se evalúa primero y devuelve una cadena.In this usage, the x:Static statement is evaluated first and returns a string. A continuación, la cadena se usa como argumento para DynamicResource.That string is then used as the argument for DynamicResource.

Extensiones de marcado y sintaxis de elementos de propiedadMarkup Extensions and Property Element Syntax

Cuando se usa como un elemento de objeto que rellena un valor de elemento de propiedad, una clase de extensión de marcado es visualmente indistinguible de un elemento de objeto típico respaldado por tipo que se puede usar en XAML.When used as an object element that fills a property element value, a markup extension class is visually indistinguishable from a typical type-backed object element that can be used in XAML. La diferencia práctica entre un elemento de objeto típico y una extensión de marcado es que la extensión de marcado se evalúa como un valor con tipo o se aplaza como una expresión.The practical difference between a typical object element and a markup extension is that the markup extension is either evaluated to a typed value or deferred as an expression. Por lo tanto, los mecanismos para detectar posibles errores de tipo de valores de propiedad para la extensión de marcado será diferente, de forma similar a cómo se trata una propiedad enlazada en tiempo de ejecución en otros modelos de programación.Therefore the mechanisms for any possible type errors of property values for the markup extension will be different, similar to how a late-bound property is treated in other programming models. Se evaluará un elemento de objeto normal para la coincidencia de tipo con la propiedad de destino que se configura al analizar el XAML.An ordinary object element will be evaluated for type match against the target property it is setting when the XAML is parsed.

La mayoría de extensiones de marcado, cuando se usan en sintaxis de elementos de objeto para rellenar un elemento de propiedad, no contienen sintaxis de elementos de contenido o de cualquier otra propiedad.Most markup extensions, when used in object element syntax to fill a property element, would not have content or any further property element syntax within. De este modo, cerraría la etiqueta de elemento de objeto y no proporcionaría ningún elemento secundario.Thus you would close the object element tag, and provide no child elements. Siempre que un procesador XAML encuentra cualquier elemento de objeto, se llama al constructor de esa clase, que crea una instancia del objeto creado a partir del elemento analizado.Whenever any object element is encountered by a XAML processor, the constructor for that class is called, which instantiates the object created from the parsed element. Una clase de extensión de marcado no es diferente: Si desea que la extensión de marcado se pueda usar en la sintaxis de elementos de objeto, debe proporcionar un constructor sin parámetros.A markup extension class is no different: if you want your markup extension to be usable in object element syntax, you must provide a parameterless constructor. Algunas extensiones de marcado existentes tienen al menos un valor de propiedad obligatorio que se debe especificar para obtener una inicialización eficaz.Some existing markup extensions have at least one required property value that must be specified for effective initialization. Si es así, ese valor de propiedad se proporciona normalmente como un atributo de propiedad en el elemento de objeto.If so, that property value is typically given as a property attribute on the object element. En las páginas de referencia Características de lenguaje (x:) de espacios de nombres XAML y Extensiones XAML de WPF, se indican las extensiones de marcado que tienen propiedades obligatorias (y los nombres de dichas propiedades).In the XAML Namespace (x:) Language Features and WPF XAML Extensions reference pages, markup extensions that have required properties (and the names of required properties) will be noted. En las páginas de referencia también se indica si la sintaxis de elementos de objeto o de atributos no se permite para extensiones de marcado concretas.Reference pages will also note if either object element syntax or attribute syntax is disallowed for particular markup extensions. Un caso destacado e es x:Array (Extensión de marcado), que no admite la sintaxis de atributos porque el contenido de la matriz debe especificarse en el etiquetado como contenido.A notable case is x:Array Markup Extension, which cannot support attribute syntax because the contents of that array must be specified within the tagging as content. El contenido de la matriz se controla como objetos generales y, por lo tanto, no es posible usar ningún convertidor de tipos predeterminado para el atributo.The array contents are handled as general objects, therefore no default type converter for the attribute is feasible. Además, x:Array (Extensión de marcado) necesita un parámetro type.Also, x:Array Markup Extension requires a type parameter.

Vea tambiénSee also