Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Using human readable enum values in a ComboBox

4.83/5 (16 votes)
31 Jan 2012CPOL 52.9K  
Sometimes, all I want is a control which allows the user to select one of several options, and tell me which one - ideally as a handy enum value. This shows a simple method which allows this.
If you have a range of values in your program, and you want the user to select one of them, the most useful (to him) is a human readable string. Unfortunately, the most useful (to you) is an enum value, and the most commonly available is the enum value name. Which means that the value name has to be carefully selected to fit both the human readable requirement, and the compiler requirement of "no special characters". Such as space.

The alternative is to load a combo box with a set of fixed strings, and then decode them into your enum values later. Which is something I avoid, as I am sure to miss one when I add options to the enum.

This Tip presents a way to fill a ComboBox with human readable strings, and tie them to enum values.

Create your enum, and give human readable Description attributes:
C#
public enum MyEnum
{
    [Description("The first")]
    the1st = 1,
    [Description("The second one")]
    the2nd = 8000,
    [Description("Another one!")]
    final = -1,
}
Then include this static method in your code:
C#
/// <summary>
/// Set the combo box to the enum values.
/// </summary>
/// <remarks>
/// If you use the Description attribute on your enum elements, that will
/// be used as the human readable ComboBox text.
/// If you don't, the enum element name will be used.
/// </remarks>
/// <example>
///         public enum MyEnum
///            {
///            [Description("The first")]
///            the1st = 1,
///            [Description("The second one")]
///            the2nd = 8000,
///            [Description("Another one!")]
///            final = -1,
///            }
///         ...
///         SetEnumValues(myComboBox, typeof(MyEnum));
/// </example>
/// <exception cref="ArgumentException">
/// Thrown if the Type supplied is not an Enum
/// </exception>
/// <param name="cb">ComboBox to set</param>
/// <param name="t">Type of enum to set values from</param>
public static void SetEnumValues(ComboBox cb, Type t)
    {
    if (!t.IsEnum)
        {
        throw new ArgumentException("Only Enum types can be set");
        }
    List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>();
    foreach (int i in Enum.GetValues(t))
        {
        string name = Enum.GetName(t, i);
        string desc = name;
        FieldInfo fi = t.GetField(name);
        // Get description for enum element
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attributes.Length > 0)
            {
            string s = attributes[0].Description;
            if (!string.IsNullOrEmpty(s))
                {
                desc = s;
                }
            }
        list.Add(new KeyValuePair<string, int>(desc, i));
        }
    // NOTE: It is very important that DisplayMember and ValueMember are set before DataSource.
    //       If you do, this works fine, and the SelectedValue of the ComboBox will be an int
    //       version of the Enum.
    //       If you don't, it will be a KeyValuePair.
    cb.DisplayMember = "Key"; 
    cb.ValueMember = "Value";
    cb.DataSource = list;
}
Call the method to set the values into your ComboBox:
C#
myComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
SetEnumValues(myComboBox, typeof(MyEnum));

The CombBox will now show the values:
The first
The second one
Another one!
You can now use the values as you wish in your ComboBox events:
C#
private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    Console.WriteLine(myComboBox.Text);
    Console.WriteLine(myComboBox.SelectedValue);
    MyEnum me = (MyEnum)myComboBox.SelectedValue;
    Console.WriteLine(me.ToString());
}
Will display:
The first
1
the1st

The second one
8000
the2nd

Another one!
-1
final

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)