WPF: a generic value converter

The task

A value converter in WPF offers the possibility to present properties in data bindings in different ways without changing the view model which contains the data property and without the need to include extra logic in XAML or code-behind. All you have to do is implement the IValueConverter interface in the converter class and use the converter in the XAML code.
The problem is if you have lots of converter implementations that you have to maintain. In larger projects, a lot of these classes can accumulate, where you basically end up coding nearly the same logic again and again, only with different types.

One solution for this problem is to use generic types for the converter. There are a lot of examples to do this for generic bool-to-value converters (e.g. in the answer here). The advantage is that the converter logic is implemented only once and the output type of the conversion is generic - although it is a concrete type in the specific converter class, but this can be done with as little as one line of code. The converted output for the bool input values (true and false) are provided in XAML, so the converter is reusable. i.e. you can implement concrete subclasses without the generic in order to have different output types for the conversion.

Taking things one step further can be done by using a generic Dictionary which can then be accessed and filled from XAML. The converter has generics for the keys and values, which are the input and output values of the converter.
There are a number of examples on the Web which solve this differently (like the post here, where there is still some logic in the concrete subclasses).

The sample code

See the repository here:
https://github.com/StefanLober/blog/tree/master/WpfApplication07

The values for the converter are provided in the converter instance. The GUI code just creates a TextBox with the enum value as text and a background brush according to the different converter values. It also adds a button to call the ChangeCommand, which cycles through the various values for the DisplayValue property. I got the syntax for using enum values in XAML here and for using keys and values here.
Here are the different display states of the application:




Nothing special, but enough to demonstrate the behavior of the controller.

Talking points

  • The sample just converts enum values to Brush instances, but it would be possible to use any type that can be defined in XAML code as key or value (i.e. source or target) for the converter.
  • As mentioned above, the code here still needs a concrete converter class without generic arguments. It should be possible to replace this by using x:TypeArguments in the XAML code to pass constraining type arguments (there is also a rather old post on MSDN solving this with MarkupExtension), but I have not tried that.
  • Note that the ConvertBack method of the converter is not used in the example, but it should work as expected (i.e. return the correct key for a given value) - if the values in the Dictionary are unique.
  • The XAML editor shows a warning because the dictionary is not "an attachable property" in the converter:
    I have not looked into the problem because the project compiles and the application works as intended anyway.

Update

  • The warning concerning the attachable property disappears if the Values dictionary is implemented using "an attached property".
  • It is possible to use the generic converter in XAML and create the concrete subclass: The downside of this is that you have to do it in a separate XAML file because the TypeArguments attribute is only allowed on the root tag. Also, it brings with it the overhead of markup compilation. So, this alternative way of specifying the generic type arguments is not really worth the effort. It would be really cool and helpful if WPF allowed a construct like this in the Resources section of the Form in order to create an anonymous class for the concrete converter and instantiate on the spot.

Comments

Popular posts from this blog

FFTMark

Visual Studio themes: VsBrushes color values