tags:

views:

10768

answers:

12

Let's say I have the following simple enum:

enum Response
{
    Yes = 1,
    No = 2,
    Maybe = 3
}

How can I bind this enum to a DropDownList control so that the descriptions are displayed in the list as well as retrieve the associated numeric value (1,2,3) once an option has been selected?

+20  A: 

I probably wouldn't bind the data as it's an enum, and it won't change after compile time (unless I'm having one of those stoopid moments).

Better just to iterate through the enum:

Dim itemValues As Array = System.Enum.GetValues(GetType(Response))
Dim itemNames As Array = System.Enum.GetNames(GetType(Response))

For i As Integer = 0 To itemNames.Length - 1
    Dim item As New ListItem(itemNames(i), itemValues(i))
    dropdownlist.Items.Add(item)
Next

Or the same in C#

Array itemValues = System.Enum.GetValues(typeof(Response));
Array itemNames = System.Enum.GetNames(typeof(Response));

for (int i = 0; i <= itemNames.Length - 1 ; i++) {
    ListItem item = new ListItem(itemNames(i), itemValues(i));
    dropdownlist.Items.Add(item);
}
Mark Glorie
Thanks a lot for this answer. GetType(Response) didn't work for me because I receive an instance of the Enum, rather than the Enum class. So I use enumInstance.GetType() instead.
Sebastian
+1  A: 

That's not quite what you're looking for, but might help:

http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx

roman m
+1  A: 

I am not sure how to do it in ASP.NET but check out this post... it might help?

Enum.GetValues(typeof(Response));
rudigrobler
+12  A: 

Use the Enumeration utility class to get an IDictionary from an Enum and then bind that to a bindable Control

    public static class Enumeration
    {
        public static IDictionary<int, string> GetAll<TEnum>() where TEnum: struct
        {
            var enumerationType = typeof (TEnum);

            if (!enumerationType.IsEnum)
                throw new ArgumentException("Enumeration type is expected.");

            var dictionary = new Dictionary<int, string>();

            foreach (int value in Enum.GetValues(enumerationType))
            {
                var name = Enum.GetName(enumerationType, value);
                dictionary.Add(value, name);
            }

            return dictionary;
        }
    }

And then use the above utility class when binding enum data to control...

ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField = "Value";
ddlResponse.DataValueField = "Key";
ddlResponse.DataBind();
Leyu
This is nice because you get both the key and the values set on a dropdownlist.
Chris
+4  A: 

As others have already said - don't databind to an enum, unless you need to bind to different enums depending on situation. There are several ways to do this, a couple of examples below.

ObjectDataSource

A declarative way of doing it with ObjectDataSource. First, create a BusinessObject class that will return the List to bind the DropDownList to:

public class DropDownData
{
    enum Responses { Yes = 1, No = 2, Maybe = 3 }

    public String Text { get; set; }
    public int Value { get; set; }

    public List<DropDownData> GetList()
    {
        var items = new List<DropDownData>();
        foreach (int value in Enum.GetValues(typeof(Responses)))
        {
            items.Add(new DropDownData
                          {
                              Text = Enum.GetName(typeof (Responses), value),
                              Value = value
                          });
        }
        return items;
    }
}

Then add some HTML markup to the ASPX page to point to this BO class:

<asp:DropDownList ID="DropDownList1" runat="server" 
    DataSourceID="ObjectDataSource1" DataTextField="Text" DataValueField="Value">
</asp:DropDownList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
    SelectMethod="GetList" TypeName="DropDownData"></asp:ObjectDataSource>

This option requires no code behind.

Code Behind DataBind

To minimize the HTML in the ASPX page and do bind in Code Behind:

enum Responses { Yes = 1, No = 2, Maybe = 3 }

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        foreach (int value in Enum.GetValues(typeof(Responses)))
        {
            DropDownList1.Items.Add(new ListItem(Enum.GetName(typeof(Responses), value), value.ToString()));
        }
    }
}

Anyway, the trick is to let the Enum type methods of GetValues, GetNames etc. to do work for you.

Johan Danforth
+11  A: 

My version is just a compressed form of the above:

foreach (Response r in Enum.GetValues(typeof(Response)))
{
    ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
    DropDownList1.Items.Add(item);
}
VanOrman
should be (int r in Enum.GetValues(typeof(Response))) or it'll just bind the description as the name and the value...
Evan
+1  A: 
public enum Color
{
    RED,
    GREEN,
    BLUE
}

Every Enum type derives from System.Enum. There are two static methods that help bind data to a drop-down list control (and retrieve the value). These are Enum.GetNames and Enum.Parse. Using GetNames, you are able to bind to your drop-down list control as follows:

protected System.Web.UI.WebControls.DropDownList ddColor;

private void Page_Load(object sender, System.EventArgs e)
{
     if(!IsPostBack)
     {
        ddColor.DataSource = Enum.GetNames(typeof(Color));
        ddColor.DataBind();
     }
}

Now if you want the Enum value Back on Selection ....

  private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
  {
   Color selectedColor = (Color)Enum.Parse(ddColor.SelectedValue); 
  }
+1  A: 

Array itemValues = Enum.GetValues(typeof(TaskStatus)); Array itemNames = Enum.GetNames(typeof(TaskStatus));

    for (int i = 0; i <= itemNames.Length; i++)
    {
        ListItem item = new ListItem(itemNames.GetValue(i).ToString(), itemValues.GetValue(i).ToString());
        ddlStatus.Items.Add(item);
    }
you found the same answer as me, this is much simpler!
bplus
+1  A: 
Mostafa
+1  A: 

Generic Code Using Answer six.

public static void BindControlToEnum(DataBoundControl ControlToBind, Type type)
{
    //ListControl

    if (type == null)
        throw new ArgumentNullException("type");
    else if (ControlToBind==null )
        throw new ArgumentNullException("ControlToBind");
    if (!type.IsEnum)
        throw new ArgumentException("Only enumeration type is expected.");

    Dictionary<int, string> pairs = new Dictionary<int, string>();

    foreach (int i in Enum.GetValues(type))
    {
        pairs.Add(i, Enum.GetName(type, i));
    }
    ControlToBind.DataSource = pairs;
    ListControl lstControl = ControlToBind as ListControl;
    if (lstControl != null)
    {
        lstControl.DataTextField = "Value";
        lstControl.DataValueField = "Key";
    }
    ControlToBind.DataBind();

}
Muhammed Qasim
+4  A: 

I use this:

Html.DropDownListFor(o => o.EnumProperty, Enum.GetValues(typeof(enumtype)).Cast<enumtype>().Select(x => new SelectListItem { Text = x.ToString(), Value = ((int)x).ToString() }))
Feryt
A: 

After finding this answer I came up with what I think is a better (at least more elegant) way of doing this, thought I'd come back and share it here.

Page_Load:

DropDownList1.DataSource = Enum.GetValues(typeof(Response));
DropDownList1.DataBind();

LoadValues:

Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString();

SaveValues:

Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text);
Ben Hughes