Как связать Enum с элементом управления DropDownList в ASP.NET?
Скажем, у меня есть следующее простое перечисление:
enum Response
{
Yes = 1,
No = 2,
Maybe = 3
}
Как связать это перечисление с элементом управления DropDownList, чтобы описания отображались в списке, а также возвращали связанное числовое значение (1,2,3) после выбора опции?
Ответы
Ответ 1
Я, вероятно, не смог бы привязать к данным как к перечислению, и он не изменится после компиляции (если у меня не будет одного из этих 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
Или то же самое в С#
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);
}
Ответ 2
Используйте следующий класс утилиты 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();
Ответ 3
Я использую это для 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() }))
Ответ 4
Моя версия представляет собой только сжатую форму выше:
foreach (Response r in Enum.GetValues(typeof(Response)))
{
ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
DropDownList1.Items.Add(item);
}
Ответ 5
public enum Color
{
RED,
GREEN,
BLUE
}
Каждый тип Enum происходит из 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();
}
}
Теперь, если вы хотите значение Enum Back on Selection....
private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(ddColor.SelectedValue);
}
Ответ 6
Как уже говорили другие, не привязывайте привязку к перечислению, если вам не нужно связываться с разными перечислениями в зависимости от ситуации. Существует несколько способов сделать это, например, несколько примеров.
ObjectDataSource
Декларативный способ сделать это с помощью ObjectDataSource. Во-первых, создайте класс BusinessObject, который вернет список, чтобы связать 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
Чтобы свести к минимуму HTML на странице ASPX и привязать его в Code Behind:
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()));
}
}
}
В любом случае, трюк заключается в том, чтобы позволить методам типа Enum GetValues, GetNames и т.д. работать для вас.
Ответ 7
После прочтения всех сообщений я придумал комплексное решение для поддержки отображения перечисления перечисления в раскрывающемся списке, а также выбор правильного значения из модели в раскрывающемся списке при отображении в режиме редактирования:
перечисление:
using System.ComponentModel;
public enum CompanyType
{
[Description("")]
Null = 1,
[Description("Supplier")]
Supplier = 2,
[Description("Customer")]
Customer = 3
}
класс расширения enum:
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()}))
Таким образом, вы можете ожидать, что ваш раскрывающийся список отобразит описание вместо значений перечисления. Также, когда дело доходит до редактирования, ваша модель будет обновлена выпадающим выбранным значением после публикации страницы.
Ответ 8
Я не уверен, как это сделать в ASP.NET, но проверьте этот пост... это может помочь?
Enum.GetValues(typeof(Response));
Ответ 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);
}
Ответ 10
public enum Color
{
RED,
GREEN,
BLUE
}
ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();
Ответ 11
Вы можете использовать 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();
Ответ 12
Общий код с использованием ответа на шесть.
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();
}
Ответ 13
После того, как я нашел этот ответ, я придумал то, что, по моему мнению, является лучшим (по крайней мере, более элегантным) способом сделать это, подумал, что я вернусь и поделился им здесь.
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);
Ответ 14
Это не совсем то, что вы ищете, но может помочь:
http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx
Ответ 15
Почему бы не использовать подобное, чтобы иметь возможность пройти каждый 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);
Ответ 16
Это мое решение для Order Enum и DataBind (текст и значение) для раскрывающегося списка с использованием 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()));
Ответ 17
Оба руководства asp.net и winforms с помощью combobox и dropdownlist:
Как использовать Enum с Combobox в С# WinForms и Asp.Net
надежды помогают
Ответ 18
По какой-то причине ответ, предоставленный Марком Глори, не работал у меня. Поскольку GetValues возвращают объект Array, и я не мог использовать indexer для получения значения его элементов. Я пробовал itemsValue.GetValue(i), и он работал, но, к сожалению, он не заполнил значение перечисления для значения элемента dropdownlist. Он просто заполнил имя элемента перечисления как текст и значение раскрывающегося списка.
Я изменил код Mark далее и разместил его как решение здесь Как связать Enum с его значением в DropDownList в ASP.NET?
Надеюсь, что это поможет.
Спасибо
Ответ 19
Отметьте мой пост о создании пользовательского помощника "ASP.NET MVC - Создание помощника DropDownList для перечислений": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx p >
Ответ 20
Если вы хотите иметь более удобное для пользователя описание в своем поле со списком (или другом элементе управления), вы можете использовать атрибут 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;
}
Ниже приведен пример перечисления с атрибутами описания:
enum SampleEnum
{
NormalNoSpaces,
[Description("Description With Spaces")]
DescriptionWithSpaces,
[Description("50%")]
Percent_50,
}
Затем Bind для управления так...
m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum));
m_Combo_Sample.DisplayMember = "Value";
m_Combo_Sample.ValueMember = "Key";
Таким образом вы можете поместить любой текст, который вы хотите в раскрывающемся списке, не имея при этом значения, как имя переменной
Ответ 21
Вы также можете использовать методы расширения. Для тех, кто не знаком с расширениями, я предлагаю проверить VB и С# документация.
Расширение 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)()
Расширение С#:
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, а затем избегаем проблем с размерами и выводами. Например, 0xFFFF0000 будет 4294901760 в качестве uint, но будет -65536 как int.
TryCast и как System.Enum немного быстрее, чем Convert.ChangeType(enumTypeValues [i], enumUnderType).ToString() (12:13 в моих тестах скорости).
Ответ 22
С тех пор ASP.NET была обновлена с некоторыми дополнительными функциями, и теперь вы можете использовать встроенное перечисление для выпадающего списка.
Если вы хотите связать себя с Enum, используйте это:
@Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response)))
Если вы привязываетесь к экземпляру Response, используйте это:
// Assuming Model.Response is an instance of Response
@Html.EnumDropDownListFor(m => m.Response)
Ответ 23
Принятое решение не работает, но приведенный ниже код поможет другим найти кратчайшее решение.
foreach (string value in Enum.GetNames(typeof(Response)))
ddlResponse.Items.Add(new ListItem()
{
Text = value,
Value = ((int)Enum.Parse(typeof(Response), value)).ToString()
});
Ответ 24
Это, вероятно, старый вопрос.. но так я и сделал.
Модель:
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" })
Это должно заполнить все в списке перечислений. Надеюсь, это поможет.