Ask Kathleen

How-to Q&A: Is There an Easy Way to Create Value Converters in Silverlight?

Ask Kathleen: Silverlight Value Converters

Value Converters in Silverlight
Q: I like the capabilities of value converters in Silverlight, but they're really a pain to write. I'm creating one for different situations, each with several conditions. For example, one converter is if something is to be made visible on true, and another is to be visible when the bound value is false. Is there a way to make this easier?

A: Value converters are extremely powerful. They implement IValueConverter, and they have two methods: Convert and ConvertBack. Value converters are valuable in minimizing the code required directly in the UI and in providing reuse of conversion logic.

One common usage is to convert Boolean values to visibility. It's easy to create a fairly large library of these conversion classes as you handle different binding scenarios such as Booleans, nulls, empty collections and non-zero values. Here are a few shortcuts to this process.

You do not need to implement ConvertBack -- it's rarely useful for display values such as Visibility, so save it for values that are actually changed by the user, such as the Text or SelectedItem properties; instead of implementing ConvertBack, just throw a not implemented exception.

You can simplify multiple visibility converters by refactoring common code into a base class. The base class implements the interface and the Convert/ConvertBack methods. The base class is abstract with an abstract method to grab the actual Boolean value:

Public MustInherit Class VisibilityConverterBase
Implements IValueConverter

Protected MustOverride Function GetBool(ByVal
value As Object) As Boolean

Derived classes will just need to implement the GetBool method while the remainder of the conversion logic remains in the base class.

Often with visibility you want to indicate that some controls are visible, and use the reverse visibility to indicate that other controls are not visible. For example, displaying a button if a value is non-zero and a message if it is zero -- perhaps a "Buy Now!" button or "Out of Stock" TextBlock.

Convert and ConvertBack support a parameter value and you can leverage this value to indicate whether to reverse the meaning of true/false. The parameter is of object type, so you can pass any value. To support reversing visibility, you can pass a Boolean true if the visibility should be reversed:

Public Function Convert(ByVal value As Object, _
ByVal targetType As System.Type, _
ByVal reverseVisibility As Object, _
ByVal culture As System.Globalization.CultureInfo) _
As Object _
Implements System.Windows.Data.
IValueConverter.Convert
If targetType IsNot GetType(Visibility) OrElse
value.GetType IsNot GetType(Boolean) Then
Return Nothing
End If
Dim reverse = False
If reverseVisibility IsNot Nothing Then
reverse = CBool(reverseVisibility)
End If

While effective, the downside of this approach is that it's not self-documenting. You can change the name of the parameter to something meaningful, but XAML doesn't have IntelliSense for conversion parameters, so this offers minimal help to programmers using your converter.

The GetBool value overridden in the derived class supplies the boolean value, and the returned visibility reflects this value and the reverse visibility flag:

Dim boolValue = GetBool(value)
If boolValue Then
Return If(reverse, Visibility.Collapsed, Visibility.Visible)
Else
Return If(reverse, Visibility.Visible, Visibility.Collapsed)
End If
End Function

Each derived class you make within your library of converters simply overrides the GetBool method:

Public Class NullToVisibilityConverter
Inherits VisibilityConverterBase

Protected Overrides Function GetBool(ByVal value
As Object) As Boolean
Return value IsNot Nothing
End Function
End Class

You use converters by adding the converter specification to your binding as a static resource. You can define the static resource at any point in your tree, but defining it in App.xaml encourages reuse across your application:

<local:NullToVisibilityConverter x:Key="NullToV
isibilityConverter" />

The binding statement in your user control or page might look like:

<TextBlock Text="{Binding Version}" 
Visibility ="{Binding MyBoolValue,
Converter={StaticResource NullToVisibilityConverter}}"/>

Silverlight 4 reduces the need for value converters for some of the most common cases such as formatting text values.

Read this month's next Ask Kathleen question: Rooting out a Binding Error.

About the Author

Kathleen is a consultant, author, trainer and speaker. She’s been a Microsoft MVP for 10 years and is an active member of the INETA Speaker’s Bureau where she receives high marks for her talks. She wrote "Code Generation in Microsoft .NET" (Apress) and often speaks at industry conferences and local user groups around the U.S. Kathleen is the founder and principal of GenDotNet and continues to research code generation and metadata as well as leveraging new technologies springing forth in .NET 3.5. Her passion is helping programmers be smarter in how they develop and consume the range of new technologies, but at the end of the day, she’s a coder writing applications just like you. Reach her at [email protected].

comments powered by Disqus

Featured

Subscribe on YouTube