Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Generic ValueConverter for Binding Enumerations to Check Boxes

0.00/5 (No votes)
15 Oct 2011 1  
Generic ValueConverter for Binding Enumerations to Check Boxes

Summary

There are many times that there are a group of radio buttons on a form that are associated with a single enumeration. What many developers will do is create a separate property in the ViewModel for each radio button. I do not like this. First I think that this is too much of a dependency between the View and the ViewModel. It also adds a whole bunch of properties to the ViewModel that just makes the ViewModel bigger, and it requires excess code for each property to convert it to and from an enumeration. All that is really needed is a single property for each enumeration, and a generic ValueConverter.

Background

After so many times of having to deal with radio buttons and ViewModels, I finally decided to create a generic way of dealing with them.

Implementation

To bind an enumeration to the IsChecked property of a group of radio buttons, a ValueConverter will be required; there is just no way to bind an enumeration to a bool without converting it. It is possible to create a separate ValueConverter class for each radio button, but that is not required since the ValueConverter methods have a parameter argument which is set in the XAML by using the ConverterParameter argument of the Binding. The idea is that each radio button IsChecked argument is bound to the Enumeration property using the EnumValueConverter with a ConverterParameter equal to a string which is the name of the specific enumeration.

class EnumValueConverter : IValueConverter
{
	public object Convert(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
	{
		if (value == null || parameter == null)
			return false;
		return value.ToString() == parameter.ToString();
	}

	public object ConvertBack(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
	{
		if (value == null || parameter == null)
			return null;
		var rtnValue = parameter.ToString();
		try
		{
			object returnEnum = Enum.Parse(targetType, rtnValue);
			return returnEnum;
		}
		catch
		{
			return null;
		}
	} 
}
Colourised in 39ms

In the example code, I have added three debug methods to aid in finding errors, but have removed these methods for clarity. As can be seen, the code is fairly straight forward. In the Convert method, the ToString() method is used to convert the enumeration from the ViewModel to a string which is then compared to the ConverterParmeter; if equal, a the value returned is true. In the ConvertBack method, the Enum.Parse method is used to convert the ConverterParmeter from the control into the appropriate enumeration for the ViewModel if the value argument in. This fortunately works because in the case of radio buttons, they only need to deal with being changed to the checked state, so never have to deal with changes to the unchecked state; that is automatic. If the Parse does not work, a null is returned (which is also the case for null value and parameter argument, which has no effect since null is invalid for an enumeration (Binding does not allow changes for invalid values).

Wiring up the XAML to the property and converter is quite straightforward. In the example, there is a very simple enum:

public enum TestEnum
{
	A, B, C
}
Colourised in 2ms

The property in the ViewModel for this enumeration is also very straightforward:

public TestEnum EnumBinding
{
	get
	{
		return _enumBinding;
	}
	set
	{
		if (_enumBinding != value)
		{
			_enumBinding = value;
			if (PropertyChanged != null)
				PropertyChanged(this, new 
				PropertyChangedEventArgs("EnumBinding"));
		}
	}
}
Colourised in 16ms

Now all that is needed is the XAML, which includes the resource definition for the converter and the checkboxes with the binding definition using the converter and the ConverterParameter:

<Window x:Class="GenericEnumValueConverter.MainWindow"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:local="clr-namespace:GenericEnumValueConverter"
		Title="Enumerator Value Converter Example" 
		Height="200" Width="250">
	<Window.Resources>
		<local:EnumValueConverter x:Key="EnumValueConverter"/>
	</Window.Resources>
	<StackPanel HorizontalAlignment="Center" 
		    VerticalAlignment="Center">
		<RadioButton Content="A" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=A}"/>
		<RadioButton Content="B" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=B}"/>
		<RadioButton Content="C" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=C}"/>
	</StackPanel>
</Window>
Colourised in 41ms

The actual example includes a TextBox to confirm that the property for the enumeration is actually the value of the radio buttons, and an extra radio button containing a bad value to show what happens when there is a bad enumeration value in the XAML (during debug, pressing the “Bad Value” radio button creates a message in the Output window).

Conclusion

This is a very clean way to connect an enumeration to radio buttons. The same converter can also be used for other purposes with a little bit of extra code, such as setting the visibility of controls based on a state that is specified by an enumeration (need to covert the bool value to a Visibility enumeration). It removes a lot of complexity from the ViewModel, and uses a single converter for all instances where enumerations are bound to a CheckBox (or another Control). In all, it is a very clean way to reduce code, and improve maintainability.

History

  • 15th October, 2011: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here