WPF – Data Binding (Radio Buttons)
Creativity shouldn’t be following radio; it should be the other way around.
Herbie Hancock
Following on from my recent post on Data Binding within WPF / MVVM, I’ve got a couple of further cases that I recently had to deal with. This post will deal with how to handle the data-binding when allowing the user to select one item from of a defined set of options, using a group of RadioButton controls. RadioButtons can be grouped either by adding them to a common parent container, or by setting the GroupName property – only one item from the group can be selected at any one time.
The key indicator property of a RadioButton IsChecked is a (nullable) boolean value, so it makes sense to have a boolean property for each RadioButton to bind to on the ViewModel, right? Actually this can quickly lead to very verbose code if you have a lot of grouped RadioButton controls. There are also potential conflicting property update issues if you re-assign the DataContext of your UI block.
What’s the alternative then? Fortunately, we already have a C# data type for selecting a specific value from a finite set – an Enum. This allows a group of related RadioButton controls to be bound to a single property. So how can we bind the boolean IsChecked property of the control to an Enum value in the ViewModel? The answer is another example of a value converter class …
public class perValueEqualsConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return parameter != null && parameter.Equals(value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value != null && value.Equals(true) ? parameter : Binding.DoNothing; } }
… which allows any bound property to be compared against a specified value – returning true or false.
The demo project for this post shows the converter in action. Each RadioButton control in a group is bound to a single enum property, just with a different value for the converter parameter.
<Grid Grid.Row="2" Grid.Column="0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="8" /> <RowDefinition Height="Auto" /> <RowDefinition Height="8" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <RadioButton Grid.Row="0" Content="A1" IsChecked="{Binding E1, Converter={StaticResource ValueEqualsConverter}, ConverterParameter={x:Static enum:DemoEnum1.A1}}" /> <RadioButton Grid.Row="2" Content="B1" IsChecked="{Binding E1, Converter={StaticResource ValueEqualsConverter}, ConverterParameter={x:Static enum:DemoEnum1.B1}}" /> <RadioButton Grid.Row="4" Content="C1" IsChecked="{Binding E1, Converter={StaticResource ValueEqualsConverter}, ConverterParameter={x:Static enum:DemoEnum1.C1}}" /> </Grid>
No BindingMode flag is required as ToggleButton.IsCheckedProperty is defined with FrameworkPropertyMetadataOptions.BindsTwoWayByDefault.
As usual the code samples for this blog are available on Github, along with my own personal C# / WPF library.
If you find this article useful, or you have any other feedback, please leave a comment below