Thursday, November 28, 2013

A simple converter

This entry references WPF 4.0

In the previous post I showed how to bind a non dependent property using styles. But the value I'm binding to is an integer and the property I'm binding to is a brush so I need a converter. This is how I did it.

1. The first thing to do is write the converter. This is a class that implements IValueConverter. I put all my converters in a single file but it's up to you. You have to write a Convert and a ConvertBack method. I didn't worry about ConvertBack because I'm only binding one way. If I pass 1 it returns a red brush otherwise it returns a black brush. It looks like this.

Public Class ErrorToBrushConverter
    Implements IValueConverter

    Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert

        If TypeOf value Is Integer Then
            Select Case value
                Case 1
                    Return New SolidColorBrush(System.Windows.Media.Colors.Red)
                Case Else
                    Return New SolidColorBrush(System.Windows.Media.Colors.Black)
            End Select
        Else
            Return New SolidColorBrush(System.Windows.Media.Colors.Black)
        End If
    End Function

    Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Return 0
    End Function
End Class

2. It is very important to build the project before the next step. Otherwise you will try to reference a class that doesn't exist which will throw an error that will prevent you from compiling the class. Catch-22.

3. Add a reference to your namespace somewhere in the logical tree so you can reference your new converter class. The easiest way is to add this to your Window or UserControl tag in the xaml. You may even have this already for other resources.

xmlns:local="clr-namespace:<your namespace>"

4. Now create a static resource in the same window or usercontrol.

<window.resources>
    <local:ErrorToBrushConverter x:Key="ErrorToBrushConverter"/>
</window.resources>

The 'ErrorToBrushConverter' after local: is the name of the converter class we wrote. The 'ErrorToBrushConverter' after x:Key is the StaticResource name we reference in the Syle tag (see the previous post). This is how we tie the two together.

So the Style line (see previous post) that says...
<Setter Property="Foreground" Value="{Binding Path=HasErrors, Converter={StaticResource ErrorToBrushConverter}}"/>

effectively takes the integer value of the HasErrors field of the underlying dataarow for this grid row (which will be 0 or 1 because that's how I wrote the SQL), finds the converter specified in the StaticResource called ErrorToBrushConverter, calls the Convert method passing the value of HasErrors, takes the return value which will be a black or red brush, and assigns it to the Foreground property. And it does this quickly.

This might seem very complex but it's really not that much more complex that writing a stylesheet and referencing it. The good new is that, like a stylesheet, it's very reusable. You can put the static resource definition in a resource file or in the application's resources so every page of your application can use it. You can even declare the Style itself as a static resource which makes attaching it to a datagridtextcolumn very simple.

No comments:

Post a Comment