Introduction
One of the things I do not believe one should do is passing WPF/Silverlight enumerations (i.e., Visibility) directly from the ViewModel to
the View. All bindings to a ViewModel that are two values should be defined as a Boolean in the ViewModel even if the View requires some other value to reduce
coupling. One of the reasons is that at times properties in the ViewModel are used in ways that were not originally intended, and using Boolean initially
the ViewModel can save making changes in the ViewModel or the creation of a value converter to convert from two values to another two values. The preferred
way should always be to use a value converter to convert the value (Boolean, or something else) to WPF. Creating a generic value converter to convert a
Boolean from the ViewModel to the enumeration (or some other value) needed by the View is actually quite easy. This can then be a value converter and can then be
customized in XAML in the View or can be defined in a resource dictionary. Such a converter can also provide additional features to aid the programmer in finding bugs.
Background
Amazingly, I was on a Silverlight project for Microsoft where Visibility was being set in the ViewModel and I actually had to convert this
Visibility to a Boolean for some other purpose using a value converter (I believe it was a Boolean). Due to administrative constraints in changes I could
make, I could not make the changes to the ViewModel (I understand that they were probably going to fix this problem, but I left the project before the fix was implemented).
I probably started directly passing WPF enumerations from the ViewModel to the View, but I was pretty quick in creating custom value
converters to do the work. It seemed wrong to have WPF enumerations in the ViewModel, and there was the IValueConverter
interface that provides the customization needed. In creating this code, I was simultaneously cursing Microsoft for not providing a simple logic within XAML
to allow for simple conversions or simple equations.
I did not like creating a custom converter for each conversion of a Boolean to some value needed in the View, and wrote a simple
value converter that could be customized for the values associated with true and false in the View’s XAML:
public class IfTrueValueConverter : IValueConverter
{
public object TrueValue { get; set; }
public object FalseValue { get; set; }
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (TrueValue == null)
{
TrueValue = true;
FalseValue = false;
}
return (bool)value ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (TrueValue == null)
{
TrueValue = true;
FalseValue = false;
}
return (value.ToString() == TrueValue.ToString());
}
}
The XAML to use this converter is very similar to using a simple converter except that true and false values are defined as part of the defining of the converter in the resources:
<Window x:Class="GenericValueConverter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GenericValueConverter"
Title="IfTrueValueConverter example" Height="350" Width="525">
<Window.Resources>
<local:IfTrueValueConverter x:Key="VisibilityConverter"
TrueValue="Visible" FalseValue="Hidden"/>
</Window.Resources>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="TestControl" Text="Test Message" Margin="5"
Visibility="{Binding IsVisible,
Converter={StaticResource VisibilityConverter}}"/>
</StackPanel>
</Window>
As can be seen, first we need to define the value converter in the Window.Resources element of the XAML. This is just defining any value converter for use except there
are two additional arguments: TrueValue and FalseValue. All that is needed is to put in the string value for the enumeration desired for when the ViewModel’s value
is true and false. The conversion capability of WPF is such that it can convert these string values into the enumeration, so the converter works. The converter
can also be used to set colors, so string values of “Red” and “Black” can be assigned to TrueValue and FalseValue, and then the converter can be used
to set the Foreground Brush.
Using the converter is now just like using any converter as can be seen in the XAML for the
TextBox.
I have used this value converter extensively in my coding, and have considered writing an article on the idea for quite a while, but I
knew I could do better. First of all, I could convert the string to the actual type so that string conversion would not be required except the first time, which
should increase performance at a small cost during initialization. Second, I could do some error checking. The main purpose of the error checking would be
to help the programmer find errors; there have been quite a few times I have spent too much time finding a problem in binding that was actually very simple,
just that WPF/Silverlight does a very poor job of helping the developer with binding problems. The two objectives actually go hand in hand since converting
a string to the required value and giving the developer feedback both require the conversion of the string to the type expected by WPF.
The important aspect of creating an implementation is converting between a string and the value, and vice versa.
I have often worked with enumerations in WPF, so was quite familiar converting strings to the enumerations and enumerations to string
values. Also, I have used the above value converter mostly for enumerations, particularly Visibility, so was only initially thinking about doing the
checking and conversion only for enumerations. When I started to implement my improved value converter, I did the enumeration part, and then thought that
it should also be able to convert strings to other object types since WPF and Silverlight do this conversion. Figuring out how to do it was a bit trickier.
I initially attempted to use the System.Convert.ChangeType method, which did not work (did not surprise me). Research found the TypeConverter
class. This class can be associated with the associated class it translates for by using an attribute:
[TypeConverter(typeof(MyClassTypeConverter))]
public class MyClass
{
}
public class MyClassTypeConverter : TypeConverter
{
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value,
Type destinationType)
{
}
}
Microsoft has type converters for many of the standard classes. All that is required is to use the static TypeDescriptor.GetConverter method,
and then the ConvertFrom method of the returned class:
TypeConverter converter = TypeDescriptor.GetConverter(targetType);
return converter.ConvertFrom(value);
I originally had a different code for conversion of the enumeration since I could use the Enum.Parse method, but the TypeConverter works
for both, and using only the TypeConverter eliminated code.
Implementation
The code for the converter is as follows:
public class IfTrueValueConverter : IValueConverter
{
public object TrueValue { get; set; }
public object FalseValue { get; set; }
private bool _checkValues;
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (!_checkValues)
Initialize(targetType);
return (bool)value ? TrueValue : FalseValue;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (!_checkValues)
Initialize(value.GetType());
return (value.ToString() == TrueValue.ToString());
}
private void Initialize(Type targetType)
{
_checkValues = true;
if (TrueValue == null)
{
TrueValue = true;
FalseValue = false;
}
else
{
TrueValue = FixValue(targetType, TrueValue);
FalseValue = FixValue(targetType, FalseValue);
}
}
private static object FixValue(Type targetType, object value)
{
if (value.GetType() == targetType)
return value;
try
{
TypeConverter converter = TypeDescriptor.GetConverter(targetType);
return converter.ConvertFrom(value);
}
catch
{
DisplayIssue(targetType, value);
return value;
}
}
[ConditionalAttribute("DEBUG")]
private static void DisplayIssue(Type targetType, object invalidValue)
{
if (targetType.IsEnum)
{
var enumNames = string.Join(", ", Enum.GetNames(targetType));
MessageBox.Show(string.Format(
"Enumeration value '{0}' not recognized for enumeration type '{1}'. " +
“Valid values are {2}.",
invalidValue, targetType, enumNames));
}
else
MessageBox.Show(string.Format(
"The value '{0}' not recognized for target type '{1}'.",
invalidValue, targetType));
}
}
The public methods are almost identical to the code above, except the creation of a private Initialize method to remove the checking out of the public methods.
The _checkValues variable allows the initializing code to be skipped once initialization has occurred. The Initialize method checks if the TrueValue
has been assigned (just like in the simpler implementation above), and makes it a Boolean if it has not. Next, the private static FixValue function
is called for each of the TrueValue and FalseValue variables. The FixValue method first checks to make sure that conversion is required: if conversion
is not required, just return the same value (if an attempt is made to convert twice, an exception will probably be raised). Otherwise, the code obtains the
TypeConverter for the targetType, and does the conversion. If there is an exception (it is not possible to convert to a value of the right
type), the code catches the exception and the original value is returned (probably this will not work, but WPF will let the code work). I have programmed
the converter so that if the environment is in debug mode, then a message box will inform the developer of the reason for the exception. This is true because the
method containing the MessageBox.Show method is decorated with “ConditionalAttribute("DEBUG")”. In this conditional method,
the target type is checked for being an enumeration so that the message box content for an enumeration can include additional information about the acceptable enumeration values.
The Example
The example included shows this converter being used for a number of different properties on a TextBox. These properties are changed by
checking CheckBoxes. One of the checkboxes controls the visibility, and this one needs to be checked to be able to see any of the other changes. Among the
properties that are bound are double (FontSize), Brush (BorderBrush), Visibility, reversed Boolean (IsReadOnly), and
Thickness (BorderThickness). This should be a pretty good variety of properties and types to show the flexibility of the value converter.

The XAML for this is as follows:
<Window x:Class="GenericValueConverter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GenericValueConverter"
Title="IfTrueValueConverter example" Height="250" Width="450">
<Window.Resources>
<local:IfTrueValueConverter x:Key="VisibilityConverter"
TrueValue="Visible" FalseValue="Hidden"/>
<local:IfTrueValueConverter x:Key="BorderColorConverter"
TrueValue="Red" FalseValue="Blue"/>
<local:IfTrueValueConverter x:Key="ReverseBoolConverter"
TrueValue="false" FalseValue="true"/>
<local:IfTrueValueConverter x:Key="BorderThicknessConverter"
TrueValue="3,4,5,6" FalseValue="1,2,3,4"/>
<local:IfTrueValueConverter x:Key="FontSizeConverter"
TrueValue="10" FalseValue="12.5"/>
</Window.Resources>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Content="checked for visible, unchecked for invisible"
IsChecked="{Binding IsVisible,FallbackValue=true}"/>
<CheckBox Content="checked for Red border color, unchecked for Blue border color"
IsChecked="{Binding BorderColor,FallbackValue=true}"/>
<CheckBox Content="checked to enable editing (IsReadOnly = false)"
IsChecked="{Binding CanEdit,FallbackValue=true}"/>
<CheckBox Content="checked for thick border thickness, unchecked for thinner"
IsChecked="{Binding ThinBorderThickness,FallbackValue=true}"/>
<CheckBox Content="checked for font size 10, unchecked for font size 12.5"
IsChecked="{Binding FontSize,FallbackValue=true}"/>
<TextBlock Text="TestControl:" Margin="0,5,0,0" Foreground="DarkBlue"/>
<TextBox Name="TestControl" Text="Test Message" Margin="5" Height="30"
Visibility="{Binding IsVisible,
Converter={StaticResource VisibilityConverter}}"
BorderBrush="{Binding BorderColor,
Converter={StaticResource BorderColorConverter}}"
BorderThickness="{Binding ThinBorderThickness,
Converter={StaticResource BorderThicknessConverter}}"
FontSize="{Binding FontSize,
Converter={StaticResource FontSizeConverter}}"
IsReadOnly="{Binding CanEdit,Converter={StaticResource
ReverseBoolConverter}}"/>
</StackPanel>
</Window>
As can be seen, using the converter is just like using the simpler one I showed above.
You will have to modify the XAML to show the debugging assistance that this code provides. All that is required is that either TrueValue or
FalseValue be assigned an invalid value when the converter is defined in the XAML. If TrueValue for Visibility is changed
to something like “illegal”, then the following MessageBox would appear:

This information should provide a lot of help in fixing binding issues for enumerations. For non-enumerations, the MessageBox is slightly simpler without the
list of valid enumeration values:

One of the nice things is that the dialog is only displayed the first time the converter is run.
There are other ways to provide feedback on translation issues, including writing to the Output window, but I prefer displaying a message to the developer.
Possible Improvements and Options
One of the ideas I have had is to extend the converter to be three-state where the third state is null. Personally, I have not seen any need for this third value in my code, but I can
see cases where a third value is desirable.
Another idea is to add properties that allow the value to be compared to something other than true and false. This would be pretty
straightforward, and could be very useful if binding to properties of a control defined in the XAML.
An extension of this would be support for more than two or three values. This could be done by defining all the items in a delimited list
in the XAML that is entered as a property in the converter. The converter would then parse the list to get the conversions.
Conclusion
This generic Boolean value converter is flexible enough to handle all Boolean conversions required by a View. It can also be used in
certain circumstances to do other binding where the value being bound to is a Boolean.
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last three years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with PIMCO in Newport Beach, CA.