如何将一个枚举绑定到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" })
这应该填充枚举列表中的所有内容。 希望这可以帮助..