TypeConverters and XAML
The TypeConverter class serves a particular purpose as part of the Silverlight implementation of XAML. Type converters process the XAML attribute values and convert attribute strings to object values when a XAML processor creates the runtime object representation. If you write a custom class, and you want instances of your class to be settable through XAML attribute values, you generally must write a custom TypeConverter class, and then apply a TypeConverterAttribute to your classes or properties that reference your type converter implementation.
This topic contains the following sections:
A XAML processor needs two pieces of information in order to process an attribute value. The first piece of information is the type of the property value that is being set. Any string that is given as an attribute value in XAML must ultimately be converted or resolved to a value that is the property's type. If the property type is a primitive, a direct conversion of the string is attempted. If the property type is an enumeration, the string is used to check for a member in that enumeration. If the property type is neither a primitive or an enumeration, then the conversion behavior of the property or type in question must be able to provide an instance of the type, or a value, based on converting the provided attribute value string.
In some cases the type conversion is native to the Silverlight XAML processor. An example of this type conversion case is values of type Point . Type conversion for Point is native to the Silverlight XAML parsing behavior and is not CLR attributed. In other cases, Silverlight implements a TypeConverter class, then attributes types or members to use it. An example of this type conversion case is values of type Nullable<bool> .
The TypeConverter Class
If the value is not a primitive type or enumeration, there is no native conversion, and there is no markup extension usage, then there must be some means of converting a String to the appropriate value or a new instance when the XAML is processed. This is the role of the TypeConverter class.
TypeConverter as a class can have other usages besides XAML; in the .NET Framework, TypeConverter existed as a class long before XAML existed. The Silverlight and WPF XAML processors and general XAML design both use the TypeConverter pattern for attribute value conversion because it is an existing coding pattern that fulfilled the conversion requirements when the type conversion involves a string source.
The Silverlight implementation of TypeConverter defines two members that are relevant for converting to and from strings for XAML processing purposes:
Of these, the most important method is ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) . This method converts the input string to the required object type.
CanConvertFrom(ITypeDescriptorContext, Type) is a support method that can be used when a service queries the capabilities of the TypeConverter implementation. You must implement CanConvertFrom(ITypeDescriptorContext, Type) to return true for certain cases, particularly for the String type.
Implement the signatures that take ITypeDescriptorContext , rather than the signatures that do not take ITypeDescriptorContext . This implementation pattern is consistent with the WPF and general .NET Framework pattern for implementing a TypeConverter , and these are the signatures that the XAML processor will call, although it may do so passing fixed values for ITypeDescriptorContext or CultureInfo in some cases. For the non- ITypeDescriptorContext signatures, your implementation should call the base implementation.
Silverlight 5 does not use ConvertTo (and CanConvertTo ) because it does not incorporate a native serialization that uses a type converter for serializing from XAML. You should still consider implementing ConvertTo (and CanConvertTo ) as a best practice for completing the wider interoperation functionality of your converter class.
The following sections describe each of the four virtual methods you must override to implement a type converter for Silverlight XAML.
To be usable as a TypeConverter implementation that supports XAML, the ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) method for that converter must accept a string as the value parameter. If the string is 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. Otherwise, the ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) implementation must return null .
Each TypeConverter implementation can have its own interpretation of what constitutes a valid string for a conversion.
Your CanConvertFrom(ITypeDescriptorContext, Type) implementation should return true for sourceType of type String , and otherwise defer to the base implementation.
Implementing CanConvertTo and ConvertTo
Do not rely on information in context , it may be null . Do not throw if context or culture is null . If input values for context or culture are null, then you should call base, passing the null context. This behavior gives a more consistent exception.
culture when called by the Silverlight XAML parser is always the en-us culture, so you can assume that behavior if you are writing a TypeConverter that supports XAML parsing. The reasons for this behavior are explained in the topic Creating Globally Aware Applications .
Culture behavior becomes particularly relevant for processing delimiters in a string syntax. For example, a comma under en-us culture cannot clash with the decimal-separator usage assigned to a comma character under some cultures. For more information, see the "Best Practices for TypeConverter Implementations" section of this topic
Support for other culture values might be useful if you intend to support type conversion for scenarios other than XAML support.
You can also provide a type converter on a per-property basis. Instead of applying a TypeConverterAttribute to the class definition, apply it to a property definition (the main definition, not the get / set accessor implementations within it). The type of the property must match the type that is processed by your custom type converter. With this attribute applied, when a XAML processor handles values of that property, it can process input strings and return object instances. The per-property type converter technique is particularly useful if you choose to use a property type where you cannot control the class definition and cannot apply a TypeConverterAttribute to the class.
TypeConverterAttribute and Derived Classes
When TypeConverterAttribute is applied to individual properties as opposed to their destination types, the property preserves the conversion behavior even if the property-owning type is derived from, so long as the original property is not shadowed.
Typically, you implement a TypeConverter for XAML in order to promote a streamlined attribute usage for one or more properties. You might do this for properties where most of the other commonly-used properties already support an attribute syntax, and requiring a property element syntax for your new property would result in overly verbose markup.
Examples of an appropriate type conversion scenario include cases where pre-existing conventions for expressing that data exist in other markup paradigms, or conventions for how that data is expressed in the written word. For example, the X,Y format for type conversion of a Point , using a comma as delimiter between X and Y, is based on presentation conventions that existed in mathematics. Another example scenario is if your property generally supports a main data type, but also supports certain special values that cannot be expressed in the main data type's string representations. An example of this type conversion scenario is Duration , which generally supports TimeSpan values (which have their own type converter for the time format), but also supports special values such as the literal string Forever . For this scenario, a best practice is to expose a static field or property on the converted type. This provides an equivalent value for code usages without requiring code users to create and invoke your type converter, passing the string token literal. If permitted by CLR rules, the field or property should have the same name as the literal that you use as the special grammar information item.
Typically, a type conversion grammar contains more than one information item. A comma is a typical choice as a separator between atoms of a string that a type converter splits and processes as parts. A space character is also often used as a separator, and many type converter implementations treat a comma or space as equivalent for separator use.
Whenever possible, apply TypeConverterAttribute to types, rather than properties, if you define the type. You should reserve TypeConverterAttribute on properties for the following cases:
You do not define the property destination type, but want to repurpose that destination type for use by your property's XAML usage.
A common type is used on more than one property, but each such property has different validation rules for which of the type's values can be supported as a value.
You define the type, but do not want that type to take a dependency on the Silverlight assemblies that are needed for TypeConverterAttribute or for CLR attributing overall.