How do you bind an Enum to a DropDownList control in ASP.NET?
假设我有以下简单的枚举:
1 2 3 4 5 6
| enum Response
{
Yes = 1,
No = 2,
Maybe = 3
} |
我如何将该枚举绑定到DropDownList控件,以便在列表中显示说明,并在选择选项后检索相关的数值(1,2,3)?
我可能不会绑定数据,因为它是一个枚举,并且在编译后它不会改变(除非我遇到那些愚蠢的时刻之一)。
最好只是遍历枚举:
1 2 3 4 5 6 7
| 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#中相同
1 2 3 4 5 6 7
| 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从枚举中获取IDictionary(枚举值和名称对);然后将IDictionary绑定到可绑定的控件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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;
}
} |
示例:使用实用程序类将枚举数据绑定到控件
1 2 3 4
| ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField ="Value";
ddlResponse.DataValueField ="Key";
ddlResponse.DataBind(); |
我将此用于ASP.NET MVC:
1
| Html.DropDownListFor(o => o.EnumProperty, Enum.GetValues(typeof(enumtype)).Cast<enumtype>().Select(x => new SelectListItem { Text = x.ToString(), Value = ((int)x).ToString() })) |
我的版本只是上述内容的压缩形式:
1 2 3 4 5
| foreach (Response r in Enum.GetValues(typeof(Response)))
{
ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
DropDownList1.Items.Add(item);
} |
1 2 3 4 5 6
| public enum Color
{
RED,
GREEN,
BLUE
} |
每个Enum类型都从System.Enum派生。有两种静态方法可帮助将数据绑定到下拉列表控件(并检索值)。它们是Enum.GetNames和Enum.Parse。使用GetNames,您可以按以下方式绑定到下拉列表控件:
1 2 3 4 5 6 7 8 9 10
| 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();
}
} |
现在,如果您希望枚举值返回"选择时..."。
1 2 3 4
| private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
} |
阅读所有文章后,我想出了一个全面的解决方案,以支持在下拉列表中显示枚举说明,以及在以"编辑"模式显示时从下拉列表的"模型"中选择适当的值:
枚举:
1 2 3 4 5 6 7 8 9 10 11 12
| using System.ComponentModel;
public enum CompanyType
{
[Description("")]
Null = 1,
[Description("Supplier")]
Supplier = 2,
[Description("Customer")]
Customer = 3
} |
枚举扩展类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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))
});
}
} |
型号类别:
1 2 3 4 5
| public class Company
{
public string CompanyName { get; set; }
public CompanyType Type { get; set; }
} |
和视图:
1 2
| @Html.DropDownListFor(m => m.Type,
@Model.Type.ToSelectList<CompanyType>()) |
并且如果您使用该下拉列表但未绑定到模型,则可以改用以下方法:
1 2 3
| @Html.DropDownList("type",
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()})) |
因此,您可以期望您的下拉列表显示"说明"而不是枚举值。同样,当涉及到"编辑"时,将在发布页面后通过下拉选定的值来更新您的模型。
正如其他人已经说过的-不要将数据绑定到枚举,除非您需要根据情况绑定到不同的枚举。有几种方法可以做到这一点,下面举几个例子。
ObjectDataSource控件
使用ObjectDataSource进行声明的方式。首先,创建一个BusinessObject类,该类将返回List以将DropDownList绑定到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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类:
1 2 3 4 5
| <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并在"隐藏代码"中进行绑定:
1 2 3 4 5 6 7 8 9 10 11 12
| 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等的Enum类型方法为您工作。
我不确定如何在ASP.NET中执行此操作,但请查看这篇文章...这可能有帮助吗?
1
| Enum.GetValues(typeof(Response)); |
您可以使用linq:
1 2 3 4 5
| 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(); |
1 2 3 4 5 6 7 8 9
| 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);
} |
1 2 3 4 5 6 7 8 9
| public enum Color
{
RED,
GREEN,
BLUE
}
ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind(); |
通用代码使用答案六。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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();
} |
找到此答案后,我想出了一种我认为更好(至少更优雅)的方法,以为我会回来在这里分享。
Page_Load中:
1 2
| DropDownList1.DataSource = Enum.GetValues(typeof(Response));
DropDownList1.DataBind(); |
LoadValues:
1 2
| Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString(); |
SaveValues:
1
| Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text); |
这可能是一个古老的问题..但这是我的工作方式。
模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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
} |
然后在"视图"中:这是使用方法填充下拉列表。
1
| @Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { @class ="form-control" }) |
这应该填充您的枚举列表中的所有内容。希望这可以帮助..
为什么不这样使用才能通过每个listControle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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();
} |
代码>
和使用一样简单:
1 2 3
| BindToEnum(typeof(NewsType), DropDownList1);
BindToEnum(typeof(NewsType), CheckBoxList1);
BindToEnum(typeof(NewsType), RadoBuuttonList1); |
代码>
此后,ASP.NET已更新为具有更多功能,现在您可以使用内置的枚举来下拉列表。
如果要绑定到枚举本身,请使用以下命令:
1
| @Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response))) |
如果要绑定到Response实例,请使用以下命令:
1 2
| // Assuming Model.Response is an instance of Response
@Html.EnumDropDownListFor(m => m.Response) |
这不是您要找的东西,但可能会有所帮助:
http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx
带组合框和下拉列表的asp.net和winforms教程:
如何在C#WinForms和Asp.Net中将Enum与Combobox一起使用
希望有所帮助
看看我关于创建自定义助手的文章" ASP.NET MVC-为枚举创建DropDownList助手":http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc -creating-A-下拉列表辅助换enums.aspx
如果您希望组合框(或其他控件)中的描述更加用户友好,则可以将Description属性与以下功能一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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属性的枚举示例:
1 2 3 4 5 6 7 8
| enum SampleEnum
{
NormalNoSpaces,
[Description("Description With Spaces")]
DescriptionWithSpaces,
[Description("50%")]
Percent_50,
} |
然后像这样绑定以进行控制...
1 2 3
| m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum));
m_Combo_Sample.DisplayMember ="Value";
m_Combo_Sample.ValueMember ="Key"; |
这样,您可以将所需的任何文本放在下拉列表中,而不必看起来像变量名
您也可以使用扩展方法。对于那些不熟悉扩展的人,建议您查看VB和C#文档。
VB扩展名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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 |
要使用扩展名:
1 2 3 4 5
| Imports <projectName>.CustomExtensions.ListItemCollectionExtension
...
yourDropDownList.Items.AddEnum(Of EnumType)() |
C#扩展名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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")));
}
}
}
} |
要使用扩展名:
1 2 3 4 5
| using CustomExtensions.ListItemCollectionExtension;
...
yourDropDownList.Items.AddEnum<EnumType>() |
如果要同时设置所选项目,请更换
1
| items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d"))) |
同
1 2 3 4
| 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和as System.Enum比Convert.ChangeType(enumTypeValues [i],enumUnderType).ToString()稍快(在我的速度测试中为12:13)。
公认的解决方案不起作用,但是下面的代码将帮助其他人寻找最短的解决方案。
1 2 3 4 5 6
| foreach (string value in Enum.GetNames(typeof(Response)))
ddlResponse.Items.Add(new ListItem()
{
Text = value,
Value = ((int)Enum.Parse(typeof(Response), value)).ToString()
}); |
这是我使用LINQ命令将枚举和数据绑定(文本和值)下拉的解决方案
1 2 3
| 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())); |
|