This post provides a simple IValueConverter implementation that makes use of the framework type converters in order to convert between a large range of source / target types. This converter can be used both within bindings and in code-behind to give more concise property setters.
Introduction
One of the great features of the XAML language is that it is flexible, concise and expressive (yes, I know that XML can be a little verbose, but if you try to create a complex UI purely in code-behind I think you will agree with my observations!). For example, you can set the fill of a rectangle by simply specifying the named color:
or ... you can specify the RGB values directly:
Looking at the above examples, you might be fooled into thinking that the Fill property is of type Color. People who are new to WPF often find that this is not the case the first time they try to bind a property of type Color to the Fill property (they would never set the Fill property directly in code behind, because that would be a cardinal sin!). The Fill property is actually of type Brush, and the XAML parser is performing some cunning type conversions in order to make the above markup work.
The solution to this problem of binding a Color to the Fill property is to create a value converter:
Which can be used as follows:
If you search google for ColorToBrushConverter, you can see that there are a great many people who have implemented this simple little converter. But what happens if you want to bind to a string representation of color? or you want to bind to a stroke dash property or path geometry? Whilst value converters are simple to implement, it is a shame that you have to create so many of them!
A Universal Value Converter
Wouldn't it be great to have a single value converter that has the same flexibility as the XAML parser? It is actually very simple to create such as converter (and after creating probably my 5th ColorToBrushConverter I have no idea why it took so long before I realised this!). The .NET framework has had an API for conversion between different types via TypeConverters for a long time. They used extensively in .NET technologies for databinding and designer support, and much more.
A value converter can obtain a suitable TypeConverter for the target property then perform the required conversion:
Note, that this value converter first tries to convert directly from the source to the target type, if this is not possible it then tried to convert via a string representation (I am not sure whether it is more correct to obtain a TypeConverter for the String type, then use this rather that invoking ToString on the value being converted, but the above works for me :-) ).
You can see this converter in action below where a range of type conversions are demonstrated:
For the first conversion, string to brush, you can use named colors, and the hex notation in its range of abbreviated forms (#AF7, #AAFF77, #FFAAFF77 ...). You can also use this converter to convert from string to their corresponding enum values, for example binding the string "Collapsed" to the Visbility property.
Value conversion in code behind
The above converter really is swiss army knife for bindings, but what about code-behind? You are still constrained by the type requirements of the property being set:
Value converters, whilst typically used in binding, can also be used directly in code-behind. The following extension method extends SetValue
method for setting dependency properties to make use of the above value converter:
Which provides a more flexible mechanism for setting property values:
... and Silverlight?
Unfortunately Silverlight lacks the TypeDescriptor class which is used to obtain TypeConveters. I am guessing that type conversion within Silverlight is 'baked-in' to the XAML parser, which means that it is not possible to re-use this logic :-(
You can download the full source for this blog post: UniversalValueConverter.zip
Regards,Colin E.