How do you bind an Enum to a DropDownList control in ASP.NET?

后端 未结 25 2340
既然无缘
既然无缘 2020-11-29 15:41

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 DropDow

相关标签:
25条回答
  • 2020-11-29 16:26

    You could also use Extension methods. For those not familar with extensions I suggest checking the VB and C# documentation.


    VB Extension:

    Namespace CustomExtensions
        Public Module ListItemCollectionExtension
    
            <Runtime.CompilerServices.Extension()> _
            Public Sub AddEnum(Of TEnum As Structure)(items As System.Web.UI.WebControls.ListItemCollection)
                Dim enumerationType As System.Type = GetType(TEnum)
                Dim enumUnderType As System.Type = System.Enum.GetUnderlyingType(enumType)
    
                If Not enumerationType.IsEnum Then Throw New ArgumentException("Enumeration type is expected.")
    
                Dim enumTypeNames() As String = System.Enum.GetNames(enumerationType)
                Dim enumTypeValues() As TEnum = System.Enum.GetValues(enumerationType)
    
                For i = 0 To enumTypeNames.Length - 1
                    items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), TryCast(enumTypeValues(i), System.Enum).ToString("d")))
                Next
            End Sub
        End Module
    End Namespace
    

    To use the extension:

    Imports <projectName>.CustomExtensions.ListItemCollectionExtension
    
    ...
    
    yourDropDownList.Items.AddEnum(Of EnumType)()
    

    C# Extension:

    namespace CustomExtensions
    {
        public static class ListItemCollectionExtension
        {
            public static void AddEnum<TEnum>(this System.Web.UI.WebControls.ListItemCollection items) where TEnum : struct
            {
                System.Type enumType = typeof(TEnum);
                System.Type enumUnderType = System.Enum.GetUnderlyingType(enumType);
    
                if (!enumType.IsEnum) throw new Exception("Enumeration type is expected.");
    
                string[] enumTypeNames = System.Enum.GetNames(enumType);
                TEnum[] enumTypeValues = (TEnum[])System.Enum.GetValues(enumType);
    
                for (int i = 0; i < enumTypeValues.Length; i++)
                {
                    items.add(new System.Web.UI.WebControls.ListItem(enumTypeNames[i], (enumTypeValues[i] as System.Enum).ToString("d")));
                }
            }
        }
    }
    

    To use the extension:

    using CustomExtensions.ListItemCollectionExtension;
    
    ...
    
    yourDropDownList.Items.AddEnum<EnumType>()
    

    If you want to set the selected item at the same time replace

    items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d")))
    

    with

    Dim newListItem As System.Web.UI.WebControls.ListItem
    newListItem = New System.Web.UI.WebControls.ListItem(enumTypeNames(i), Convert.ChangeType(enumTypeValues(i), enumUnderType).ToString())
    newListItem.Selected = If(EqualityComparer(Of TEnum).Default.Equals(selected, saveResponseTypeValues(i)), True, False)
    items.Add(newListItem)
    

    By converting to System.Enum rather then int size and output issues are avoided. For example 0xFFFF0000 would be 4294901760 as an uint but would be -65536 as an int.

    TryCast and as System.Enum are slightly faster than Convert.ChangeType(enumTypeValues[i], enumUnderType).ToString() (12:13 in my speed tests).

    0 讨论(0)
  • 2020-11-29 16:27

    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);
    }
    
    0 讨论(0)
  • 2020-11-29 16:27

    This is my solution for Order an Enum and DataBind(Text and Value)to Dropdown using LINQ

    var mylist = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToList<MyEnum>().OrderBy(l => l.ToString());
    foreach (MyEnum item in mylist)
        ddlDivisao.Items.Add(new ListItem(item.ToString(), ((int)item).ToString()));
    
    0 讨论(0)
  • 2020-11-29 16:28

    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);
    }
    
    0 讨论(0)
  • 2020-11-29 16:28

    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);
    
    0 讨论(0)
  • 2020-11-29 16:28

    Why not use like this to be able pass every listControle :

    
    public static void BindToEnum(Type enumType, ListControl lc)
            {
                // get the names from the enumeration
                string[] names = Enum.GetNames(enumType);
                // get the values from the enumeration
                Array values = Enum.GetValues(enumType);
                // turn it into a hash table
                Hashtable ht = new Hashtable();
                for (int i = 0; i < names.Length; i++)
                    // note the cast to integer here is important
                    // otherwise we'll just get the enum string back again
                    ht.Add(names[i], (int)values.GetValue(i));
                // return the dictionary to be bound to
                lc.DataSource = ht;
                lc.DataTextField = "Key";
                lc.DataValueField = "Value";
                lc.DataBind();
            }
    
    And use is just as simple as :
    
    BindToEnum(typeof(NewsType), DropDownList1);
    BindToEnum(typeof(NewsType), CheckBoxList1);
    BindToEnum(typeof(NewsType), RadoBuuttonList1);
    

    0 讨论(0)
提交回复
热议问题