Скажем, у меня есть следующее простое перечисление:
enum Response
{
Yes = 1,
No = 2,
Maybe = 3
}
Как я могу привязать это перечисление к элементу управления DropDownList, чтобы описания отображались в списке, а также извлекали соответствующее числовое значение (1,2,3) после выбора параметра?





Я, вероятно, не стал бы связывать данных, поскольку это перечисление, и оно не изменится после времени компиляции (если только у меня не будет одного из тех моментов сутулый).
Лучше просто перебрать перечисление:
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);
}
Используя C#, у меня это не работает, потому что и getValues, и getNames возвращают одно и то же, первый как объекты, а второй как строка. Определение перечисления выглядит так: public enum eResult {Right = 1, NoncontrolledError = 2,}
Кстати, в C# вы не можете получить доступ к Array с индексом itemNames [i], вы можете сделать это только с arrayObject.GetValue (i), и таким образом он возвращает только имя в обоих случаях.
Я решил смешать это решение с этим stackoverflow.com/questions/3213432/…
itemValues (i) вернет объект, если вам нужно значение, вы всегда можете выполнить Convert.ToInt32 (itemValues (i)), который даст вам целое число
Если вам нужны эти значения: Выберите вариант: Да, Нет, Может быть с Select an option в качестве первого значения? Для использования значений Enum в фильтре (поиск) и значение необязательный для поиска. Если выбрано Выберите вариант, не применять значение перечисления к поиску.
Почему так много положительных отзывов. Код (по крайней мере, C#) теперь работает и содержит синтаксические ошибки.
Это не совсем то, что вы ищете, но может помочь:
http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx
Я не уверен, как это сделать в ASP.NET, но посмотрите сообщение это ... это может помочь?
Enum.GetValues(typeof(Response));
Используйте следующий служебный класс Enumeration, чтобы получить IDictionary<int,string> (пара значений Enum и имени) из Перечисление; затем вы привязываете IDictionary к привязываемому 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();
+1. Я использовал его, но я думаю, что ключ и значение ошибочны. Это должно вернуть IDictionary <string, int>
Следует отметить, что это не будет вести себя правильно для всех типов перечислений (например, uint, ulong, long и т. д.). Обычно наиболее эффективным полем для поиска является ключ. В этом случае это будет int, поскольку целые числа представляют собой простое сравнение <, =,> и сравнение строк <и> для каждого символа.
Как уже говорили другие - не привязывайте данные к перечислению, если вам не нужно привязываться к разным перечислениям в зависимости от ситуации. Есть несколько способов сделать это, пара примеров ниже.
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 и выполнить привязку в коде позади:
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 и т. д. Работать за вас.
Моя версия - это просто сжатая форма приведенного выше:
foreach (Response r in Enum.GetValues(typeof(Response)))
{
ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
DropDownList1.Items.Add(item);
}
должен быть (int r в Enum.GetValues (typeof (Response))) или просто привяжет описание как имя и значение ...
это не работает, поскольку оно вставляет имя члена перечисления в значение ListItem. Преобразование в int будет работать в большинстве случаев, но не в том случае, если перечисление имеет тип uint, ulong или long.
Намного лучшее решение ИМХО.
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 вернулось к выделению ...
private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
}
хороший ответ, но небольшой совет: 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);
}
Почему бы не использовать это, чтобы передать каждый 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);
Общий код с использованием ответа шесть.
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();
LoadValues:
Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString();
SaveValues:
Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text);
Это мое решение для заказа 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()));
Учебник по asp.net и winforms с комбинированным списком и раскрывающимся списком: Как использовать Enum с Combobox в C# WinForms и Asp.Net
надежда помогает
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
Если вы хотите иметь более понятное описание в поле со списком (или другом элементе управления), вы можете использовать атрибут 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";
Таким образом, вы можете поместить любой текст в раскрывающийся список без необходимости выглядеть как имя переменной.
Вы также можете использовать методы расширения. Для тех, кто не знаком с расширениями, я предлагаю проверить документацию 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 позволяет избежать проблем с размером и выводом. Например, 0xFFFF0000 будет 4294901760 как uint, но будет -65536 как int.
TryCast и как System.Enum немного быстрее, чем Convert.ChangeType (enumTypeValues [i], enumUnderType) .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>())
и если вы используете это раскрывающееся меню без привязки к модели, вы можете использовать это вместо этого:
@Html.DropDownList("type",
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()}))
Таким образом, вы можете ожидать, что в раскрывающемся списке будет отображаться описание вместо значений перечисления. Кроме того, когда дело доходит до редактирования, ваша модель будет обновлена выбранным значением в раскрывающемся списке после публикации страницы.
Красиво сделано, особенно бит с аннотациями [Описание]. Я буду применять эту технику.
Аккуратное и чистое объяснение. Престижность Амир !!
С тех пор ASP.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" })
Это должно заполнить все в вашем списке перечислений. Надеюсь это поможет..
Однако это работает, вам нужен класс расширения, если вы хотите включать строковые литералы с пробелами.
Это лучший ответ. @Nikul, тебе не нужен класс расширения. Вам нужно только использовать аннотации. [Display(Name = "Option number one")] Option1,
Вы можете сделать это намного короче
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#, которое работает с любым drop и enum ...
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, но я хотел предоставить решение, которое я недавно использовал для проекта Windows Forms на C#. Идея состоит в том, чтобы создать словарь, в котором ключи - это имена перечислимых элементов, а значения - это перечисленные значения. Затем вы привязываете словарь к полю со списком. См. Универсальную функцию, которая принимает в качестве аргументов 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));
Большое спасибо за этот ответ. GetType (Response) у меня не сработал, потому что я получил экземпляр Enum, а не класс Enum. Поэтому вместо этого я использую enumInstance.GetType ().