You can do an awful lot of cool stuff with the Windows Forms controls that come bundled with Visual Studio. Unfortunately, the binding of enumerated values to a group of buttons isn't one of them. This article introduces a control designed to do just that.
I was slapping together a quick prototype at work the other day when I realized what I need was a control that I could use to display enumerated values as radio buttons. I didn't remember there being anything built into Visual Studio that would do the trick, so I did a quick online search. The closest thing I found to what I was looking for was this article by Jay Andrew Allen. However, his control didn't allow me to specify the enumerated type I wanted to display and have the control automatically create the buttons for me. A couple of hours later, I had created the control I wanted.
Using the Code
EnumButtonGroup control is a Windows Forms
UserControl that exposes the additional properties
SelectedValue and a
ValueType property is used to specify the .NET
Type that represents the enumerated values that will be displayed in the control.
public Type ValueType
if (value != null && !value.IsEnum)
throw new ArgumentException("Argument must be an enumerated type");
this.valueType = value;
if (this.valueType == null)
this.selectedValue = null;
When this property is set, the control first checks to see if it represents an enumerated type. If so, it automatically creates the buttons that represent the values of that enumerated type. The
SelectedValue property is then set to the first enumerated value and any subscribers are notified via the
SelectedValue property is used to specify which of the enumerated values displayed in the control will be selected (checked).
public object SelectedValue
if (this.valueType != null)
this.selectedValue = value;
SelectedValue property is set automatically in response to a
CheckChanged event from one of the buttons, the control simply notifies any subscribers of the change via the
SelectedValueChanged event. If the property is set directly then the appropriate button's
Checked property is set to
true, which in turn causes the
SelectedValueChanged event to be raised.
Applications that want to be notified when the
SelectedValue property changes should register to receive
public void MainForm_Load(object sender, EventArgs e)
private void enumButtonGroup1_SelectedValueChanged(object sender, EventArgs e)
this.propertyGrid1.SelectedObject = sender;
I wanted the
ValueType property to be editable at design-time as well as run-time. To enable this, I needed to add a type converter (
StringToTypeConverter) to convert a
string to a
ValueType to be specified in
One point of special note: The
Type.GetType() method will return
null if the type isn't in an assembly loaded by the application or in the mscorlib.dll assembly.
I also wanted the
SelectedValue property to be editable at design-time. This meant I needed to add a UI type editor (
EnumButtonGroupSelectedValueEditor) to display drop-down list of possible values from which to select.
Points of Interest
You may have noticed that I also added some other properties:
Orientation is an enumerated value that allows the buttons to be oriented either horizontally or vertically within the control
ShowDescriptions is a boolean property that controls whether enumerated values marked with the
DescriptionAttribute will have their description displayed
HideObsoleteValues is a boolean property that controls whether enumerated values marked with the
ObsoleteAttribute will be displayed
Some possible additions that would make this control more useful are:
- Specifying different layouts that would allow the buttons to be arranged in rows and columns
- Displaying enumerated values marked with the
FlagsAttribute as check boxes
The attached project is a Visual Studio 2008 / .NET 3.5 project. If anyone would like a Visual Studio 2005 / .NET 2.0 version, please let me know and I'll upload one.
- 6th December, 2008: Initial submission
- 9th December, 2008: Added Visual Studio 2005 version. Renamed
HideObsoleteValues to correct inverse logic bug.
This is my first article submission. I will appreciate any feedback.