TypeConverters and XAML
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 Extensible Application Markup Language (XAML) attribute usage. If you write a custom class, and you want instances of your class to be usable as Extensible Application Markup Language (XAML) settable attribute values, you might need to apply a TypeConverterAttribute to your class, write a custom TypeConverter class, or both.
This topic contains the following sections.
- XAML and String Values
- Implementing a Type Converter
- Applying the TypeConverterAttribute
- Related Topics
XAML and String Values
When you set an attribute value in XAML, the initial type of that value is String. Even other primitives such as Double are initially strings to a XAML processor, although the conversion to other nonstring primitive values or from named values of an enumeration is relatively straightforward because of built-in type conversions.
A XAML processor needs two pieces of information in order to process an attribute value. The first piece of information is the value type of the property that is being set. 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. If the value is a primitive, a direct conversion of the string is attempted. If the value is an enumeration, the string is used to check for a name match in that enumeration. If the value is neither a primitive or 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.
TypeConverter
If the value is not a primitive type or enumeration, 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 XAML is processed. This is the role of the TypeConverter implementation. TypeConverter defines four members that are relevant for converting to and from strings for XAML processing purposes:
Of these, the most important method is ConvertFrom. This method converts the input string to the required object type.
The next most important method is ConvertTo. If a WPF application is converted to a markup representation (for instance, if it is saved to XAML), ConvertTo is responsible for producing a markup representation.
CanConvertTo and CanConvertFrom are support methods that are used when a service queries the capabilities of the TypeConverter implementation. You must implement these methods to return true for certain cases, particularly for the String type.
Type Converters and Markup Extensions
Markup extensions and type converters fill orthogonal roles in terms of XAML processor behavior and the scenarios that they are applied to. 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. 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.
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. At best, a stateless type converter could only generate a new instance, which might not be desirable. For more information on markup extensions, see Markup Extensions and XAML.
Implementing a Type Converter
Implementing ConvertFrom
To be usable as a TypeConverter implementation that supports XAML, the ConvertFrom method for that converter must accept a string as the value parameter. 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. Otherwise, the ConvertFrom implementation must return null.
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. 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.
Note
Do not use the curly brace characters, particularly {, as a possible element of your string format. These characters are reserved as the entry and exit for a markup extension sequence.
Implementing ConvertTo
ConvertTo is potentially used for serialization support. Serialization support for your custom type is not an absolute requirement. 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.
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. When the destinationType parameter is type String, then the returned object must castable to String. The returned string must represent a serialized value of value. 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.
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.
If destinationType parameter is not of type String, you can choose your own converter handling. Typically, you would revert to base implementation handling.
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.
Note
Do not use the curly brace characters, particularly {, as a possible element of your string format. These characters are reserved as the entry and exit for a markup extension sequence.
Implementing CanConvertTo
Your CanConvertTo implementation should return true for destinationType of type String, and otherwise defer to the base implementation.
Implementing CanConvertFrom
Your CanConvertFrom implementation should return true for sourceType of type String, and otherwise defer to the base implementation.
Applying the TypeConverterAttribute
In order for your custom type converter to be used as the acting type converter for a custom class, you must apply the .NET Framework attribute TypeConverterAttribute to your class definition. The ConverterTypeName that you specify through the attribute must be the type name of your custom type converter. 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.
You can also provide a type converter on a per-property basis. Instead of applying a .NET Framework attribute TypeConverterAttribute to the class definition, apply it to a property definition (the main definition, not the get/set 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 from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a TypeConverterAttribute there.