如何在 ASP.NET 中将 Enum 绑定到 DropDownList 控件?

假设我有以下简单枚举:

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

如何将此枚举绑定到 DropDownList 控件,以便在选择选项后在列表中显示描述并检索相关的数值(1,2,3) ?

184265 次浏览

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

最好只迭代枚举:

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

我不知道如何做到这一点在 ASP.NET,但检查 这个后... 它可能会有帮助?

Enum.GetValues(typeof(Response));

使用下面的实用工具类 Enumeration枚举获得一个 IDictionary<int,string>(Enum 值和名称对) ; 然后将 字典绑定到一个可绑定的 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;
}
}

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

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

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

ObjectDataSource

使用 ObjectDataSource 进行此操作的声明性方法。首先,创建一个 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;
}
}

然后向 ASPX 页面添加一些 HTML 标记,以指向这个 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()));
}
}
}

不管怎样,诀窍是让 GetValue、 GetNames 等的 Enum 类型方法为您工作。

我的版本只是上述内容的压缩形式:

foreach (Response r in Enum.GetValues(typeof(Response)))
{
ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
DropDownList1.Items.Add(item);
}
public enum Color
{
RED,
GREEN,
BLUE
}

每个枚举类型都派生自 System。Enum.有两种静态方法可以帮助将数据绑定到下拉列表控件(并检索值)。这些是 Enum。获取名称和枚举。解析。通过使用 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();
}
}

现在,如果您想要枚举值返回到选择..。

  private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
}
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);
}

为什么不像这样使用以便能够通过每个 listControl:


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

使用答案6的泛型代码。

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


}

我在 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() }))

在找到这个答案之后,我想出了一个我认为更好(至少更优雅)的方法来做这件事,我想我应该回来在这里分享一下。

Page _ Load:

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

负载值:

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

保存价值:

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

这是我使用 LINQ 命令枚举和 DataBind (文本和值)下拉的解决方案

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

Net 和 winform 教程都有 combobox 和下拉列表: 如何在 C # WinForms 和 Asp.Net 中使用 Enum 和 Combobox

希望有用

public enum Color
{
RED,
GREEN,
BLUE
}


ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();

看看我关于创建自定义助手的文章“ ASP.NET MVC-为枚举创建 DropDownList 助手”: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx

如果你想在你的组合框(或其他控件)中有一个更加用户友好的描述,你可以使用描述属性和下面的函数:

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

通过这种方式,您可以在下拉列表中放置任何您想要的文本,而不必使它看起来像一个变量名

您还可以使用扩展方法。对于那些不熟悉扩展的人,我建议查看 VBC # 文档。


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。可以避免枚举而不是整数大小和输出问题。例如,0xFFFF0000将4294901760作为一个 uint,但将 -65536作为一个 int。

TryCast 和 as System. Enum 比 Convert. ChangeType (枚举类型值[ i ] ,枚举类型) . ToString ()(在我的速度测试中是12:13)稍微快一些。

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

枚举:

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

如果你使用的下拉菜单没有绑定到 Model,你可以使用这个代替:

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

因此通过这样做,您可以期望您的下拉列表显示描述,而不是枚举值。另外,当涉及到编辑,您的模型将更新后,下拉选择值张贴页面。

NET 后来更新了一些功能,您现在可以使用内置枚举来下拉。

如果要绑定 Enum 本身,请使用以下命令:

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

如果要绑定 Response 实例,请使用以下方法:

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

你可以用 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();

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

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

这将填充枚举列表中的所有内容。希望这有所帮助..。

你可以做得更短

public enum Test
{
Test1 = 1,
Test2 = 2,
Test3 = 3
}
class Program
{
static void Main(string[] args)
{


var items = Enum.GetValues(typeof(Test));


foreach (var item in items)
{
//Gives you the names
Console.WriteLine(item);
}




foreach(var item in (Test[])items)
{
// Gives you the numbers
Console.WriteLine((int)item);
}
}
}

对于我们中那些想要一个可用于任何删除和枚举的 C # 解决方案的人来说..。

private void LoadConsciousnessDrop()
{
string sel_val = this.drp_Consciousness.SelectedValue;
this.drp_Consciousness.Items.Clear();
string[] names = Enum.GetNames(typeof(Consciousness));
    

for (int i = 0; i < names.Length; i++)
this.drp_Consciousness.Items.Add(new ListItem(names[i], ((int)((Consciousness)Enum.Parse(typeof(Consciousness), names[i]))).ToString()));


this.drp_Consciousness.SelectedValue = String.IsNullOrWhiteSpace(sel_val) ? null : sel_val;
}

我知道这篇文章比较老,而且适用于 Asp.net,但是我想提供一个我最近用于 c # Windows 窗体项目的解决方案。其思想是构建一个字典,其中键是枚举元素的名称,值是枚举值。然后将字典绑定到组合框。查看一个将 ComboBox 和 Enum Type 作为参数的泛型函数。

    private void BuildComboBoxFromEnum(ComboBox box, Type enumType) {
var dict = new Dictionary<string, int>();
foreach (var foo in Enum.GetValues(enumType)) {
dict.Add(foo.ToString(), (int)foo);
}
box.DropDownStyle = ComboBoxStyle.DropDownList; // Forces comboBox to ReadOnly
box.DataSource = new BindingSource(dict, null);
box.DisplayMember = "Key";
box.ValueMember = "Value";
// Register a callback that prints the Name and Value of the
// selected enum. This should be removed after initial testing.
box.SelectedIndexChanged += (o, e) => {
Console.WriteLine("{0} {1}", box.Text, box.SelectedValue);
};
}

这一功能可用于以下方面:

BuildComboBoxFromEnum(comboBox1,typeof(Response));

在 ASP.NET Core 中,您可以使用以下 Html 助手(来自 Microsoft. AspNetCore.Mvc.Rending) :

<select asp-items="Html.GetEnumSelectList<GridReportingStatusFilters>()">
<option value=""></option>
</select>