Reusable WPF RadioButton Control (Data Binding to enum)
Reusable WPF RadioButton control which takes the pain away
Introduction
I needed to add a simple 3 choice selection to my WPF project, using RadioButton
control seemed an obvious choice, but the amount of work for such a simple task was ridiculous. So I ended up creating a reusable control with a pretty simple usage.
Background
The idea of the control is to simply pass an array of Enum
s (or string
s) and it will create the radio button for each one. Then, just handle OnSelectionChanged
event.
Here are the screenshots from the attached example application. First group of three RadioButton
s are added as Enum
s with text labels. The second group of three RadioButton
s are added as array of three string
s.
Using the Code
From XAML point of view, the usage is very simple:
<my:RadioButtonCtrl x:Name="radioButtonCtrl" Margin="2,2,2,2" />
In code behind, add list of items, button labels (Content
) will be Enum
names converted to String
:
radioButtonCtrl.Add(MyEnum.Enum1, MyEnum.Enum2, MyEnum.Enum3);
Alternatively, you can add string
s instead of Enum
:
radioButtonCtrl.Add("Item1", "Item2", "Item3");
Another option is to add an array of String
/Enum
pairs, in this case the String
is used as a button label (Content
) and the Enum
will be passed to OnSelectionChanged
event:
radioButtonCtrl.Add(
new RadioButtonCtrl.MyPair("Item1", MyEnum.Enum1),
new RadioButtonCtrl.MyPair("Item2", MyEnum.Enum2),
new RadioButtonCtrl.MyPair("Item3", MyEnum.Enum3)
);
To programmatically set the selected button, use Selected
property. You can pass the button index, label or the Enum
tag, all have the same result:
radioButtonCtrl.Selected = 0;
radioButtonCtrl.Selected = "Item1";
radioButtonCtrl.Selected = MyEnum.Enum1;
To handle the selection, add OnSelectionChanged
event handler:
radioButtonCtrl.OnSelectionChanged +=
new RadioButtonCtrl.SelectedEventHandler(radioButtonCtrl_OnSelectionChanged);
void radioButtonCtrl_OnSelectionChanged(object sender, RadioButtonCtrl.SelectedEventArgs e)
{
label1.Content = String.Format("Selected: {0} ({1}), Group: '{2}'",
e.NewSelection, e.NewSelection.GetType().Name, e.Group);
}
Please note that if you add more than one RadioButtonControl
to your window, it's recommended that for each control you should set a unique Group name, otherwise Microsoft becomes confused. Also, currently Group name should be set before calling Add()
function.
radioButtonCtrl2.Group = "Group 2";
radioButtonCtrl2.Add("Item1", "Item2", "Item3");
This way, you can also use single OnSelectionChanged
even handler for multiple groups (if you want), the group name will be passed in the RadioButtonCtrl.SelectedEventArgs
, see the attached example code.
Layout Options
![]() |
To change the Horizontal alignment of buttons, use radioButtonCtrl2.FlowDirection = FlowDirection.RightToLeft;
Fig 2. Group 2 FlowDirection is set to "FlowDirection.RightToLeft".
|
![]() |
For the Vertical button alignment, there are also two options. If control But if the control <my:RadioButtonCtrl Grid.Row="0" Height="80" x:Name="radioButtonCtrl1" />
<my:RadioButtonCtrl Grid.Row="1" Height="NaN" x:Name="radioButtonCtrl2" />
Fig 3. Group 1 Height is set explicitly and doesn't change when the window is resized.
|
Points of Interest
If you are just after a quick solution for the RadioButton
problem - download the RadioButtonControl.dll and include it in your project. Usage should be pretty straight forward.
Otherwise, if you want to know how it works, please download the source code and have a look.
The only point of interest which is worth mentioning here is the RadioButton.IsChecked
property DataBinding
implementation. Since the RadioButton
s are added to the control from the code, not XAML, the DataBinding
should be created in the code as well.
To simplify DataBinding
creation, I added a simple MyBinding
class. The interesting part here is the IValueConverter
implementation to link the buttons IsChecked
property to the RadioButtonCtrl.Selected
property.
public void Add(string label, Enum tag = null)
{
RadioButton btn = new RadioButton();
...
if (tag == null)
{
btn.Tag = label;
}
else
{
btn.Tag = tag;
}
MyBinding binding1 = new MyBinding("Selected", this, new EnumMatchToBooleanConverter(), btn.Tag);
btn.SetBinding(RadioButton.IsCheckedProperty, binding1);
...
stackPanel.Children.Add(btn);
}
The converter implementation is based on Christian Moser article. I slightly modified the converter implementation to support both RadioButton
s usage scenarios - using just the String
label or using the Enum
Tag.
History
I'm planning to change OnSelectionChanged
event handler to WPF-ish style using Dependency Property. Currently, it's a quick piece of work, but it works and works well.