Introduction
The solution presented here provides a simple and tidy way to bind Enum
s to a ComboBox
or (with only minor adjustments) to any other bindable control. If you decorated your Enum
-members with a DescriptionAttribute, that description can be used as the DisplayMember
for the Control-Binding, otherwise the name of the Enum
-member can be used instead.
Background
The idea for this tip/trick originates from my answer to a recent question in CodeProject Q&A where in a comment it was suggested that I write it up as a tip/trick. The inquirer of the Q&A-question had troubles implementing a solution proposed to a question on Code Review (StackExchange) which is where the original code comes from (especially StackExchange-Member Jesse C. Slicer). I only claim credit for making it a generic solution (along with some other minor improvements) and packing it up into a tidy sample.
Using the Code
The sample uses these two Enum
-definitions - one with, one without Description-Attributes:
public enum AnimalOption
{
[Description("flying animal")]
Bird,
[Description("best friend")]
Dog,
[Description("cuddly carnivore")]
Cat
}
public enum ShapeOption
{
Circle,
Rectangle,
Line
}
They get bound to ComboBox
es in the constructor of the Form
. As you can see, it's done via a generic extension method to ComboBox
that takes the Enum
-Type as generic type argument and a DisplayMode
-argument that tells whether it should look for Description-Attributes to use for the DisplayMember
or use the name of the Enum
-Member instead (ValueToString
).
public Form1()
{
InitializeComponent();
AnimalComboBox.BindEnum<AnimalOption>(DisplayMode.DescriptionAttribute);
ShapeComboBox.BindEnum<ShapeOption>(DisplayMode.ValueToString);
}
The implementation of the extension method and its "helpers" is as follows:
public class EnumBindingItem<TEnum>
{
public string Description { get; private set; }
public TEnum Value { get; set; }
public EnumBindingItem(string description, TEnum value)
{
Description = description;
Value = value;
}
}
public enum DisplayMode
{
DescriptionAttribute,
ValueToString
}
public static class EnumBindingExtension
{
public static void BindEnum<TEnum>(this ComboBox cbo, DisplayMode mode)
{
cbo.DataSource = Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Select(value => CreateEnumBindingItem(value, mode))
.OrderBy(item => item.Value)
.ToList();
cbo.DisplayMember = "Description";
cbo.ValueMember = "Value";
}
private static EnumBindingItem<TEnum> CreateEnumBindingItem<TEnum>(TEnum value, DisplayMode mode)
{
string description;
if (mode == DisplayMode.DescriptionAttribute)
{
FieldInfo enumMember = typeof(TEnum).GetField(value.ToString());
DescriptionAttribute attribute = (DescriptionAttribute)
Attribute.GetCustomAttribute(enumMember, typeof(DescriptionAttribute));
description = attribute.Description;
}
else
{
description = value.ToString();
}
return new EnumBindingItem<TEnum>(description, value);
}
}
In the SelectedValueChanged
-EventHandlers of the ComboBox
es, you can then easily get the selected Enum
-value like this:
private void AnimalComboBoxSelectedValueChanged(object sender, EventArgs e)
{
AnimalOption selectedAnimal = ((EnumBindingItem<AnimalOption>)AnimalComboBox.SelectedItem).Value;
AnimalSelectionLabel.Text = selectedAnimal.ToString();
}
private void ShapeComboBoxSelectedValueChanged(object sender, EventArgs e)
{
ShapeOption selectedShape = ((EnumBindingItem<ShapeOption>)ShapeComboBox.SelectedItem).Value;
ShapeSelectionLabel.Text = selectedShape.ToString();
}
I hope it's useful to you! Comments are welcome!
History
- v1.1 - March 16, 2015
- Incorporated the suggestion from Klaus Luedenscheidt and one of Sergey Alexandrovich Kryukov's suggestions. No functional changes.
- v1.0 - March 15, 2015