Introduction
While building a user interface for things like an options dialog, you may want to represent a Boolean, enumeration, and sometimes an integer or string property with a group of radio buttons.
Background
I did some research and found quite a few articles on how to do this using a converter. However, most of the solutions were cumbersome, built for a specific type and had a long thread of questions/issues.
Here is the most comprehensive post that I found: http://stackoverflow.com/a/2908885/2005727. This solution is inspired by this post, and I wanted to go further and provide a complete code sample.
The Solution
You need to use a converter parameter to specify which value a radio button corresponds to. If your property equals to this value, this button will be checked, and other buttons unchecked. This solution works regardless whether you set the GroupName property or not, though you should normally set it.
Here is an example on how to do this in XAML for a Boolean property:
<RadioButton GroupName="BooleanGroup"
IsChecked="{Binding BoolProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={x:Static src:MainWindow.BooleanTrue}}">
</RadioButton>
<RadioButton GroupName="BooleanGroup"
IsChecked="{Binding BoolProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={x:Static src:MainWindow.BooleanFalse}}">
</RadioButton>
Note that I defined two static Boolean members in my class so I can use the static binding in XAML. Alternatively, you can set the converter parameter in a less concise way as described here: http://stackoverflow.com/questions/3978937/how-to-pass-an-integer-as-converterparameter.
Another interesting approach is to use resources instead of the static binding, as discussed here: http://stackoverflow.com/questions/4997446/boolean-commandparameter-in-xaml.
<Application.Resources>
<system:Boolean x:Key="True">True</system:Boolean>
<system:Boolean x:Key="False">False</system:Boolean>
</Application.Resources>
<RadioButton GroupName="BooleanGroup"
IsChecked="{Binding BoolProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={StaticResource True}}">
</RadioButton>
<RadioButton GroupName="BooleanGroup"
IsChecked="{Binding BoolProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={StaticResource False}}">
</RadioButton>
Here is an example for an enumeration:
<RadioButton GroupName="EnumGroup"
IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={x:Static src:TestEnum.Option1}}">
</RadioButton>
<RadioButton GroupName="EnumGroup"
IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={x:Static src:TestEnum.Option2}}">
</RadioButton>
<RadioButton GroupName="EnumGroup"
IsChecked="{Binding EnumProperty, Converter={StaticResource RadioButtonCheckedConverter},
ConverterParameter={x:Static src:TestEnum.Option3}}">
</RadioButton>
The same approach can be applied for string and integer properties. Here is the code of the converter, which is the same regardless of the property type:
public class RadioButtonCheckedConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
}
Please note that this solution will not work for flag enumeration properties (e.g. you want to bind a set of check boxes to a single property). You can find a solution for flag enumeration types in the article referenced in the background section above.
History
Initial post.