Clases TypeConverter y XAMLTypeConverters and XAML

En este tema se presenta el propósito de la conversión de tipos desde cadenas como característica general del lenguaje XAML.This topic introduces the purpose of type conversion from string as a general XAML language feature. En el .NET Framework, la clase TypeConverter sirve para un propósito determinado como parte de la implementación de una clase personalizada administrada que se puede usar como un valor de propiedad en el uso de atributos XAML.In the .NET Framework, the TypeConverter class serves a particular purpose as part of the implementation for a managed custom class that can be used as a property value in XAML attribute usage. Si escribe una clase personalizada y desea que las instancias de la clase se puedan usar como valores de atributo que se pueden establecer en XAML, puede que tenga que aplicar un TypeConverterAttribute a la clase, escribir una clase de TypeConverter personalizada o ambas cosas.If you write a custom class, and you want instances of your class to be usable as XAML settable attribute values, you might need to apply a TypeConverterAttribute to your class, write a custom TypeConverter class, or both.

Conceptos de la conversión de tiposType Conversion Concepts

Valores de cadena y XAMLXAML and String Values

Cuando se establece un valor de atributo en un archivo XAML, el tipo inicial de ese valor es una cadena en texto puro.When you set an attribute value in a XAML file, the initial type of that value is a string in pure text. Incluso otros tipos primitivos como Double son cadenas de texto inicialmente para un procesador XAML.Even other primitives such as Double are initially text strings to a XAML processor.

Un procesador XAML necesita dos fragmentos de información para procesar un valor de atributo.A XAML processor needs two pieces of information in order to process an attribute value. El primer fragmento de información es el tipo de valor de la propiedad que se va a establecer.The first piece of information is the value type of the property that is being set. Cualquier cadena que defina un valor de atributo y que se procese en XAML se tiene que convertir o resolver en última instancia en un valor de ese tipo.Any string that defines an attribute value and that is processed in XAML must ultimately be converted or resolved to a value of that type. Si el valor es un primitivo que el analizador XAML entiende (por ejemplo, un valor numérico), se tratará de convertir la cadena directamente.If the value is a primitive that is understood by the XAML parser (such as a numeric value), a direct conversion of the string is attempted. Si el valor es una enumeración, se usa la cadena para comprobar una coincidencia de nombre con una constante con nombre en esa enumeración.If the value is an enumeration, the string is used to check for a name match to a named constant in that enumeration. Si el valor no es un primitivo que el analizador entiende ni una enumeración, entonces el tipo en cuestión debe poder proporcionar una instancia del tipo, o un valor, basado en una cadena convertida.If the value is neither a parser-understood primitive nor an enumeration, then the type in question must be able to provide an instance of the type, or a value, based on a converted string. Esto se hace indicando una clase de convertidor de tipos.This is done by indicating a type converter class. El convertidor de tipos es, en realidad, una clase del asistente para proporcionar valores de otra clase, tanto para el escenario de XAML como, potencialmente, para las llamadas de código en el código de .NET Framework.The type converter is effectively a helper class for providing values of another class, both for the XAML scenario and also potentially for code calls in .NET code.

Usar el comportamiento de conversión de tipos existente en XAMLUsing Existing Type Conversion Behavior in XAML

Dependiendo de la medida en que esté familiarizado con los conceptos de XAML subyacentes, es posible que ya use el comportamiento de conversión de tipos en aplicaciones XAML básicas sin darse cuenta.Depending on your familiarity with the underlying XAML concepts, you may already be using type conversion behavior in basic application XAML without realizing it. Por ejemplo, WPF define literalmente cientos de propiedades que toman un valor de tipo Point.For instance, WPF defines literally hundreds of properties that take a value of type Point. Un Point es un valor que describe una coordenada en un espacio de coordenadas bidimensional y, en realidad, solo tiene dos propiedades importantes: X y Y.A Point is a value that describes a coordinate in a two-dimensional coordinate space, and it really just has two important properties: X and Y. Cuando se especifica un punto en XAML, se especifica como una cadena con un delimitador (normalmente una coma) entre el X y Y valores que se proporcionan.When you specify a point in XAML, you specify it as a string with a delimiter (typically a comma) between the X and Y values you provide. Por ejemplo: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>.For example: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>.

Incluso este tipo simple de Point y su uso simple en XAML implican un convertidor de tipos.Even this simple type of Point and its simple usage in XAML involve a type converter. En este caso, es la clase PointConverter.In this case that is the class PointConverter.

El convertidor de tipos de Point definido en el nivel de clase simplifica los usos de marcado de todas las propiedades que toman Point.The type converter for Point defined at the class level streamlines the markup usages of all properties that take Point. Si en este caso no hubiera un convertidor de tipos, se necesitaría el marcado siguiente, mucho más detallado, para obtener el mismo ejemplo mostrado previamente:Without a type converter here, you would need the following much more verbose markup for the same example shown previously:

<LinearGradientBrush>
  <LinearGradientBrush.StartPoint>
    <Point X="0" Y="0"/>
  </LinearGradientBrush.StartPoint>
  <LinearGradientBrush.EndPoint>
    <Point X="1" Y="1"/>
  </LinearGradientBrush.EndPoint>
</LinearGradientBrush>

La decisión entre usar la cadena de conversión de tipos o una sintaxis equivalente más detallada suele depender del estilo de codificación.Whether to use the type conversion string or a more verbose equivalent syntax is generally a coding style choice. Es posible que el flujo de trabajo de las herramientas de XAML también influya en el modo de establecer los valores.Your XAML tooling workflow might also influence how values are set. Algunas herramientas de XAML suelen crear la forma más detallada del marcado porque facilita la operación de ida y vuelta en las vistas de los diseñadores o su propio mecanismo de serialización.Some XAML tools tend to emit the most verbose form of the markup because it is easier to round-trip to designer views or its own serialization mechanism.

Por lo general, los convertidores de tipos existentes se pueden detectar en WPF y en tipos de .NET Framework mediante la comprobación de una clase (o propiedad) para la presencia de un TypeConverterAttributeaplicado.Existing type converters can generally be discovered on WPF and .NET Framework types by checking a class (or property) for the presence of an applied TypeConverterAttribute. Este atributo denominará la clase que es el convertidor de tipos para los valores de ese tipo, tanto para los fines de XAML como, potencialmente, para otros propósitos.This attribute will name the class that is the supporting type converter for values of that type, for XAML purposes as well as potentially other purposes.

Convertidores de tipos y extensiones de marcadoType Converters and Markup Extensions

Las extensiones de marcado y los convertidores de tipos rellenan los roles ortogonales en lo que se refiere al comportamiento del procesador XAML y los escenarios a los que se aplican.Markup extensions and type converters fill orthogonal roles in terms of XAML processor behavior and the scenarios that they are applied to. Aunque el contexto está disponible para los usos de la extensión de marcado, en las implementaciones de extensión de marcado no se suele comprobar el comportamiento de conversión de tipos de aquellas propiedades en las que una extensión de marcado proporciona un valor.Although context is available for markup extension usages, type conversion behavior of properties where a markup extension provides a value is generally is not checked in the markup extension implementations. En otras palabras, aunque una extensión de marcado devuelva una cadena de texto como salida de ProvideValue, no se invoca el comportamiento de la conversión de tipos en esa cadena tal y como se aplica a una propiedad concreta o al tipo de valor de propiedad. Generalmente, el propósito de una extensión de marcado es procesar una cadena y devolver un objeto sin ningún convertidor de tipos implicado.In other words, even if a markup extension returns a text string as its ProvideValue output, type conversion behavior on that string as applied to a specific property or property value type is not invoked, Generally, the purpose of a markup extension is to process a string and return an object without any type converter involved.

Una situación común en la que es necesario usar una extensión de marcado en lugar de un convertidor de tipos es cuando se hace referencia a un objeto que ya existe.One common situation where a markup extension is necessary rather than a type converter is to make a reference to an object that already exists. En el mejor de los casos, un convertidor de tipos sin estado solamente podría generar una nueva instancia, lo que podría no ser conveniente.At best, a stateless type converter could only generate a new instance, which might not be desirable. Para más información sobre las extensiones de marcado, vea Extensiones de marcado y XAML de WPF.For more information on markup extensions, see Markup Extensions and WPF XAML.

Convertidores de tipos nativosNative Type Converters

En la implementación de WPF y .NET Framework del analizador de XAML, hay algunos tipos que presentan un control nativo de la conversión de tipos, si bien no se trata de tipos que puedan considerarse primitivos por convención.In the WPF and .NET Framework implementation of the XAML parser, there are certain types that have native type conversion handling, yet are not types that might conventionally be thought of as primitives. Un ejemplo de este tipo es DateTime.An example of such a type is DateTime. El motivo de esto se basa en cómo funciona la arquitectura de .NET Framework: el tipo DateTime se define en mscorlib, la biblioteca más básica de .NET.The reason for this is based on how the .NET Framework architecture works: the type DateTime is defined in mscorlib, the most basic library in .NET. DateTime no se puede atribuir con un atributo que proceda de otro ensamblado que introduzca una dependencia (TypeConverterAttribute proviene del sistema), por lo que no se admite el mecanismo de detección de convertidores de tipos habitual mediante atribución.DateTime is not permitted to be attributed with an attribute that comes from another assembly that introduces a dependency (TypeConverterAttribute is from System) so the usual type converter discovery mechanism by attributing cannot be supported. En su lugar, el analizador de XAML tiene una lista de tipos que necesitan este procesamiento nativo y los procesa de manera parecida a los primitivos auténticos.Instead, the XAML parser has a list of types that need such native processing and processes these similarly to how the true primitives are processed. (En el caso de DateTime esto implica una llamada a Parse).(In the case of DateTime this involves a call to Parse.)

Implementación de un convertidor de tiposImplementing a Type Converter

TypeConverterTypeConverter

En el Point ejemplo dado anteriormente, se mencionó la clase PointConverter.In the Point example given previously, the class PointConverter was mentioned. En el caso de las implementaciones de .NET de XAML, todos los convertidores de tipos que se usan para los propósitos de XAML son clases que derivan de la clase base TypeConverter.For .NET implementations of XAML, all type converters that are used for XAML purposes are classes that derive from the base class TypeConverter. La clase TypeConverter existía en las versiones de .NET Framework que preceden a la existencia de XAML; uno de sus usos originales era proporcionar la conversión de cadenas para los cuadros de diálogo de propiedades en los diseñadores visuales.The TypeConverter class existed in versions of .NET Framework that precede the existence of XAML; one of its original usages was to provide string conversion for property dialogs in visual designers. En el caso de XAML, el rol de TypeConverter se expande para incluir la clase base de las conversiones to-String y from-String que habilitan el análisis de un valor de atributo de cadena y, posiblemente, el procesamiento de un valor en tiempo de ejecución de una propiedad de objeto determinado de nuevo en una cadena para serialización como atributo.For XAML, the role of TypeConverter is expanded to include being the base class for to-string and from-string conversions that enable parsing a string attribute value, and possibly processing a run-time value of a particular object property back into a string for serialization as an attribute.

TypeConverter define cuatro miembros que son relevantes para la conversión a y desde cadenas para fines de procesamiento de XAML:TypeConverter defines four members that are relevant for converting to and from strings for XAML processing purposes:

De estos, el método más importante es ConvertFrom.Of these, the most important method is ConvertFrom. Este método convierte la cadena de entrada en el tipo de objeto necesario.This method converts the input string to the required object type. En realidad, el método ConvertFrom podría implementarse para convertir una gama mucho más amplia de tipos en el tipo de destino previsto del convertidor y, por tanto, atender los propósitos que van más allá de XAML, como admitir conversiones en tiempo de ejecución, pero para los propósitos de XAML es solo la ruta de acceso del código que puede procesar una entrada String que sea importante.Strictly speaking, the ConvertFrom method could be implemented to convert a much wider range of types into the converter's intended destination type, and thus serve purposes that extend beyond XAML such as supporting run-time conversions, but for XAML purposes it is only the code path that can process a String input that matters.

El siguiente método más importante es ConvertTo.The next most important method is ConvertTo. Si una aplicación se convierte en una representación de marcado (por ejemplo, si se guarda en XAML como un archivo), ConvertTo es responsable de generar una representación de marcado.If an application is converted to a markup representation (for instance, if it is saved to XAML as a file), ConvertTo is responsible for producing a markup representation. En este caso, la ruta de acceso del código que es importante para XAML es cuando se pasa una destinationType de String.In this case, the code path that matters for XAML is when you pass a destinationType of String .

CanConvertTo y CanConvertFrom son métodos de compatibilidad que se usan cuando un servicio consulta las capacidades de la implementación de TypeConverter .CanConvertTo and CanConvertFrom are support methods that are used when a service queries the capabilities of the TypeConverter implementation. Estos métodos se tienen que implementar para obtener true en los casos específicos de tipo que los métodos de conversión equivalentes de su convertidor admiten.You must implement these methods to return true for type-specific cases that the equivalent conversion methods of your converter support. Para los propósitos de XAML, esto suele traducirse en el tipo String .For XAML purposes, this generally means the String type.

Información de referencia cultural y convertidores de tipos para XAMLCulture Information and Type Converters for XAML

Cada implementación de TypeConverter puede tener su propia interpretación de lo que constituye una cadena válida para una conversión y también puede usar o ignorar la descripción de tipo que se pasa como parámetros.Each TypeConverter implementation can have its own interpretation of what constitutes a valid string for a conversion, and can also use or ignore the type description passed as parameters. Existe una consideración importante con respecto a la referencia cultural y a la conversión de tipos de XAML.There is an important consideration with regard to culture and XAML type conversion. XAML admite plenamente el uso de cadenas traducibles como valores de atributo.Using localizable strings as attribute values is entirely supported by XAML. Pero no se admite el uso de esa cadena traducible como entrada del convertidor de tipos con requisitos de referencia cultural concretos, porque los convertidores de tipos para los valores de atributo de XAML requieren necesariamente un comportamiento de análisis de lenguaje fijo mediante la referencia cultural en-US.But using that localizable string as type converter input with specific culture requirements is not supported, because type converters for XAML attribute values involve a necessarily fixed-language parsing behavior, using en-US culture. Para más información sobre las razones de diseño que motivan esta restricción, vea la especificación del lenguaje XAML ([MS-XAML]).For more information on the design reasons for this restriction, you should consult the XAML language specification ([MS-XAML]).

Un ejemplo que ilustra por qué una referencia cultural puede ser un problema, es que algunas referencias culturales usan una coma como delimitador de separador decimal para los números.As an example where culture can be an issue, some cultures use a comma as their decimal point delimiter for numbers. Esto entra en conflicto con el comportamiento de muchos de los convertidores de tipos de XAML de WPF, consistente en usar una coma como delimitador (basándose en precedentes históricos como el formato X,Y común o las listas delimitadas por comas).This will collide with the behavior that many of the WPF XAML type converters have, which is to use a comma as a delimiter (based on historical precedents such as the common X,Y form, or comma delimited lists). El problema tampoco se resuelve pasando una referencia cultural en el XAML circundante (estableciendo Language o xml:lang en la referencia cultural sl-SI, que es una de las que usan la coma para separar los decimales de esta manera).Even passing a culture in the surrounding XAML (setting Language or xml:lang to the sl-SI culture, an example of a culture that uses a comma for decimal in this way) does not solve the issue.

Implementación de ConvertFromImplementing ConvertFrom

Para ser igual de utilizable que una implementación de TypeConverter que admite XAML, el método ConvertFrom para ese convertidor tiene que aceptar una cadena como parámetro value .To be usable as a TypeConverter implementation that supports XAML, the ConvertFrom method for that converter must accept a string as the value parameter. Si la cadena tiene un formato válido y la implementación de TypeConverter puede convertirla, el objeto devuelto debe admitir una conversión al tipo esperado por la propiedad.If the string was in valid format, and can be converted by the TypeConverter implementation, then the returned object must support a cast to the type expected by the property. De lo contrario, la implementación de ConvertFrom debe devolver null.Otherwise, the ConvertFrom implementation must return null.

Cada implementación de TypeConverter puede tener su propia interpretación de lo que constituye una cadena válida para una conversión y también puede usar o ignorar la descripción del tipo o los contextos de referencia cultural pasados como parámetros.Each TypeConverter implementation can have its own interpretation of what constitutes a valid string for a conversion, and can also use or ignore the type description or culture contexts passed as parameters. Pero es posible que el procesamiento de XAML de WPF no pase valores al contexto de descripción del tipo en todos los casos y que tampoco pase referencias culturales basadas en xml:lang.However, the WPF XAML processing might not pass values to the type description context in all cases, and also might not pass culture based on xml:lang.

Nota

No use los caracteres de llave, en concreto {, como elementos posibles del formato de cadena.Do not use the curly brace characters, particularly {, as a possible element of your string format. Estos caracteres están reservados como entrada y salida de una secuencia de extensión de marcado.These characters are reserved as the entry and exit for a markup extension sequence.

Implementación de ConvertToImplementing ConvertTo

ConvertTo se usa en teoría para admitir la serialización.ConvertTo is potentially used for serialization support. La compatibilidad con la serialización a través de ConvertTo para el tipo personalizado y su convertidor de tipos no es un requisito imprescindible.Serialization support through ConvertTo for your custom type and its type converter is not an absolute requirement. Pero, si implementa un control, o usa la serialización como parte de las características o del diseño de la clase, conviene implementar ConvertTo.However, if you are implementing a control, or using serialization of as part of the features or design of your class, you should implement ConvertTo.

Para que se pueda usar como una implementación TypeConverter que admite XAML, el método de ConvertTo para ese convertidor debe aceptar una instancia del tipo (o un valor) que se admita como el parámetro value.To be usable as a TypeConverter implementation that supports XAML, the ConvertTo method for that converter must accept an instance of the type (or a value) being supported as the value parameter. Cuando el parámetro destinationType es el tipo String, el objeto devuelto debe poder convertirse en String.When the destinationType parameter is the type String, then the returned object must be able to be cast as String. La cadena devuelta debe representar un valor serializado de value.The returned string must represent a serialized value of value. Idealmente, el formato de serialización elegido debe ser capaz de generar el mismo valor si esa cadena se pasa a la implementación de ConvertFrom del mismo convertidor, sin una pérdida significativa de información.Ideally, the serialization format you choose should be capable of generating the same value if that string were passed to the ConvertFrom implementation of the same converter, without significant loss of information.

Si el valor no se puede serializar o el convertidor no admite la serialización, la implementación de ConvertTo debe devolver nully se le permite producir una excepción en este caso.If the value cannot be serialized, or the converter does not support serialization, the ConvertTo implementation must return null, and is permitted to throw an exception in this case. Pero si inicia excepciones, debe notificar la imposibilidad de usar esa conversión como parte de la implementación de CanConvertTo para que se admita el procedimiento recomendado de comprobar con CanConvertTo primero para evitar excepciones.But if you do throw exceptions, you should report the inability to use that conversion as part of your CanConvertTo implementation so that the best practice of checking with CanConvertTo first to avoid exceptions is supported.

Si destinationType parámetro no es de tipo String, puede elegir su propio control de convertidor.If destinationType parameter is not of type String, you can choose your own converter handling. Normalmente, se revertiría a la administración de la implementación base, que en el ConvertTo método genera una excepción específica.Typically, you would revert to base implementation handling, which in the basemost ConvertTo raises a specific exception.

Implementación de CanConvertToImplementing CanConvertTo

Su implementación de CanConvertTo debe devolver true para destinationType de tipo Stringo, si no, respetar la implementación base.Your CanConvertTo implementation should return true for destinationType of type String, and otherwise defer to the base implementation.

Implementación de CanConvertFromImplementing CanConvertFrom

Su implementación de CanConvertFrom debe devolver true para sourceType de tipo Stringo, si no, respetar la implementación base.Your CanConvertFrom implementation should return true for sourceType of type String, and otherwise defer to the base implementation.

Aplicación de TypeConverterAttributeApplying the TypeConverterAttribute

Para que un procesador XAML utilice el convertidor de tipos personalizado como convertidor de tipos que actúa para una clase personalizada, debe aplicar el TypeConverterAttribute a la definición de clase.In order for your custom type converter to be used as the acting type converter for a custom class by a XAML processor, you must apply the TypeConverterAttribute to your class definition. El ConverterTypeName que se especifica a través del atributo debe ser el nombre de tipo del convertidor de tipos personalizado.The ConverterTypeName that you specify through the attribute must be the type name of your custom type converter. Con este atributo aplicado, cuando un procesador XAML controla valores en los que el tipo de propiedad usa el tipo de la clase personalizada, puede especificar cadenas y devolver instancias de objeto.With this attribute applied, when a XAML processor handles values where the property type uses your custom class type, it can input strings and return object instances.

También puede proporcionar un convertidor de tipos por cada propiedad.You can also provide a type converter on a per-property basis. En lugar de aplicar un TypeConverterAttribute a la definición de clase, aplíquelo a una definición de propiedad (la definición principal, no a la get/set implementaciones que contiene).Instead of applying a TypeConverterAttribute to the class definition, apply it to a property definition (the main definition, not the get/set implementations within it). El tipo de la propiedad tiene que coincidir con el tipo que el convertidor de tipos personalizado procesa.The type of the property must match the type that is processed by your custom type converter. Con este atributo aplicado, cuando un procesador XAML controla valores de esa propiedad, puede procesar cadenas de entrada y devolver instancias de objeto.With this attribute applied, when a XAML processor handles values of that property, it can process input strings and return object instances. La técnica de convertidor de tipos por propiedad resulta especialmente útil si decide usar un tipo de propiedad de Microsoft .NET Framework o de otra biblioteca donde no se puede controlar la definición de clase y no se puede aplicar un TypeConverterAttribute allí.The per-property type converter technique is particularly useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a TypeConverterAttribute there.

Vea tambiénSee also