如何将一个枚举绑定到ASP.NET中的DropDownList控件?

比方说,我有以下简单的枚举:

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

如何将此枚举绑定到DropDownList控件,以便在列表中显示说明,并且一旦select了选项,就可以检索相关的数值(1,2,3)?

我可能不会绑定数据,因为它是一个枚举,它不会在编译时间后改变(除非我有一个stoopid时刻)。

更好的只是遍历枚举:

 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 

或者在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); } 

使用下面的工具类Enumeration从一个Enumeration中获取一个IDictionary<int,string> (枚举值和名称对) 然后将IDictionary绑定到可绑定的控件。

 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; } } 

示例:使用实用程序类将枚举数据绑定到控件

 ddlResponse.DataSource = Enumeration.GetAll<Response>(); ddlResponse.DataTextField = "Value"; ddlResponse.DataValueField = "Key"; ddlResponse.DataBind(); 

我的版本只是上面的压缩forms:

 foreach (Response r in Enum.GetValues(typeof(Response))) { ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString()); DropDownList1.Items.Add(item); } 

我用这个ASP.NET MVC

 Html.DropDownListFor(o => o.EnumProperty, Enum.GetValues(typeof(enumtype)).Cast<enumtype>().Select(x => new SelectListItem { Text = x.ToString(), Value = ((int)x).ToString() })) 
 public enum Color { RED, GREEN, BLUE } 

每个枚举types派生自System.Enum。 有两个静态方法可以帮助将数据绑定到下拉列表控件(并检索值)。 这些是Enum.GetNames和Enum.Parse。 使用GetNames,你可以绑定到你的下拉列表控件,如下所示:

 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(); } } 

现在,如果你想要枚举值返回select….

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

正如其他人已经说过的 – 不要将数据绑定到一个枚举,除非需要根据情况绑定到不同的枚举。 有几种方法可以做到这一点,下面的几个例子。

ObjectDataSource控件

用ObjectDataSource进行声明的方式。 首先,创build一个BusinessObject类,该类将返回List以将DropDownList绑定到:

 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; } } 

然后添加一些HTML标记到ASPX页面来指向这个BO类:

 <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> 

这个选项不需要代码。

DataBind后面的代码

为了最小化ASPX页面中的HTML并在代码隐藏中进行绑定:

 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())); } } } 

无论如何,诀窍是让GetValues,GetNames等Enumtypes的方法为你工作。

阅读所有文章后,我想出了一个全面的解决scheme,以支持在下拉列表中显示枚举描述,以及在编辑模式下显示时从下拉列表中select适当的值:

枚举:

 using System.ComponentModel; public enum CompanyType { [Description("")] Null = 1, [Description("Supplier")] Supplier = 2, [Description("Customer")] Customer = 3 } 

枚举扩展类:

 using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Web.Mvc; public static class EnumExtension { public static string ToDescription(this System.Enum value) { var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false); return attributes.Length > 0 ? attributes[0].Description : value.ToString(); } public static IEnumerable<SelectListItem> ToSelectList<T>(this System.Enum enumValue) { return System.Enum.GetValues(enumValue.GetType()).Cast<T>() .Select( x => new SelectListItem { Text = ((System.Enum)(object) x).ToDescription(), Value = x.ToString(), Selected = (enumValue.Equals(x)) }); } } 

模型类:

 public class Company { public string CompanyName { get; set; } public CompanyType Type { get; set; } } 

和查看:

 @Html.DropDownListFor(m => m.Type, @Model.Type.ToSelectList<CompanyType>()) 

如果您使用的是没有绑定到模型的下拉菜单,则可以使用下面的代码:

 @Html.DropDownList("type", Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>() .Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()})) 

所以通过这样做,你可以期望你的下拉菜单显示的是描述而不是枚举值。 另外,在编辑时,您的模型将在发布页面后通过下拉select的值进行更新。

我不知道如何在ASP.NET中做到这一点,但看看这个post…它可能有帮助吗?

 Enum.GetValues(typeof(Response)); 
 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); } 
 public enum Color { RED, GREEN, BLUE } ddColor.DataSource = Enum.GetNames(typeof(Color)); ddColor.DataBind(); 

通用代码使用答案六。

 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(); } 

find这个答案之后,我想出了我认为是更好的(至less是更优雅的)这样做的方式,以为我会回来在这里分享。

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); 

你可以使用linq:

 var responseTypes= Enum.GetNames(typeof(Response)).Select(x => new { text = x, value = (int)Enum.Parse(typeof(Response), x) }); DropDownList.DataSource = responseTypes; DropDownList.DataTextField = "text"; DropDownList.DataValueField = "value"; DropDownList.DataBind(); 

为什么不这样使用就可以通过每个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(); } 

而使用就像下面这样简单:

 BindToEnum(typeof(NewsType), DropDownList1); BindToEnum(typeof(NewsType), CheckBoxList1); BindToEnum(typeof(NewsType), RadoBuuttonList1); 

这是我的解决scheme使用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())); 

出于某种原因, Mark Glorie提供的答案并不适合我。 由于GetValues返回一个Array对象,我不能使用索引器获取它的项目值。 我试过itemsValue.GetValue(我),它的工作,但不幸的是,它没有填充枚举值的下拉列表项的值。 它只是将枚举项名称填充为下拉列表的文本和值。

我进一步修改了Mark的代码,并把它作为解决scheme在这里发布如何将一个枚举的值绑定到ASP.NET中的DropDownList?

希望这可以帮助。

谢谢

看看我的post创build一个自定义的助手“ASP.NET MVC – 创build一个枚举的DropDownList助手”: http : //blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc -creating-A-下拉列表辅助换enums.aspx

如果您希望在combobox(或其他控件)中使用更友好的描述,则可以使用以下函数的Description属性:

  public static object GetEnumDescriptions(Type enumType) { var list = new List<KeyValuePair<Enum, string>>(); foreach (Enum value in Enum.GetValues(enumType)) { string description = value.ToString(); FieldInfo fieldInfo = value.GetType().GetField(description); var attribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).First(); if (attribute != null) { description = (attribute as DescriptionAttribute).Description; } list.Add(new KeyValuePair<Enum, string>(value, description)); } return list; } 

下面是一个应用了Description属性的枚举的例子:

  enum SampleEnum { NormalNoSpaces, [Description("Description With Spaces")] DescriptionWithSpaces, [Description("50%")] Percent_50, } 

然后绑定来控制像这样…

  m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum)); m_Combo_Sample.DisplayMember = "Value"; m_Combo_Sample.ValueMember = "Key"; 

这样,你可以把任何你想要的文本放在下拉菜单中,而不必像variables名一样

你也可以使用扩展方法。 对于那些不熟悉扩展的人,我build议检查VB和C#文档。


VB扩展:

 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 

要使用扩展名:

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

C#扩展:

 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"))); } } } } 

要使用扩展名:

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

如果您想要同时设置所选项目,请更换

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

 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) 

通过转换为System.Enum而不是int大小和输出问题可以避免。 例如,0xFFFF0000作为uint将是4294901760,但将作为int的-65536。

TryCast和System.Enum比Convert.ChangeType(enumTypeValues [i],enumUnderType).ToString()(12:13在我的速度testing)稍快。

使用combobox和下拉列表的asp.net和winforms教程: 如何在C#WinForms和Asp.Net中使用Enum和Combobox

希望有帮助

ASP.NET已经更新了一些更多的function,现在你可以使用内置的枚举来下拉菜单。

如果你想绑定Enum本身,使用这个:

 @Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response))) 

如果你绑定了一个Response实例,使用这个:

 // Assuming Model.Response is an instance of Response @Html.EnumDropDownListFor(m => m.Response) 

接受的解决scheme不起作用,但下面的代码将帮助其他人寻求最短的解决scheme。

  foreach (string value in Enum.GetNames(typeof(Response))) ddlResponse.Items.Add(new ListItem() { Text = value, Value = ((int)Enum.Parse(typeof(Response), value)).ToString() }); 

这可能是一个古老的问题..但这是我做了我的。

模型:

 public class YourEntity { public int ID { get; set; } public string Name{ get; set; } public string Description { get; set; } public OptionType Types { get; set; } } public enum OptionType { Unknown, Option1, Option2, Option3 } 

然后在视图中:这里是如何使用填充下拉菜单。

 @Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { @class = "form-control" }) 

这应该填充枚举列表中的所有内容。 希望这可以帮助..