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].