Digamos que tengo la siguiente enumeración simple:
enum Response
{
Yes = 1,
No = 2,
Maybe = 3
}
¿Cómo puedo enlazar esta enumeración a un control DropDownList para que las descripciones se muestren en la lista, así como recuperar el valor numérico asociado (1,2,3) una vez que se haya seleccionado una opción?
Probablemente no lo haría vinculo los datos, ya que son una enumeración, y no cambiarán después del tiempo de compilación (a menos que tenga uno de esos stoopid moment).
Mejor solo para iterar a través de la enumeración:
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
O lo mismo en 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);
}
Use la siguiente clase de utilidad Enumeration
para obtener un IDictionary<int,string>
(par de valor y nombre de enumeración) de una Enumeración ; a continuación, enlaza el IDictionary a un Control enlazable.
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;
}
}
Ejemplo: Usar la clase de utilidad para enlazar datos de enumeración a un control
ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField = "Value";
ddlResponse.DataValueField = "Key";
ddlResponse.DataBind();
Yo uso esto para 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() }))
Mi versión es solo una forma comprimida de lo anterior:
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
}
Cada tipo Enum deriva de System.Enum. Hay dos métodos estáticos que ayudan a enlazar datos a un control de lista desplegable (y recuperar el valor). Estos son Enum.GetNames y Enum.Parse. Con GetNames, puede enlazar a su control de lista desplegable de la siguiente manera:
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();
}
}
Ahora si quieres que el valor Enum vuelva a la selección ...
private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
{
Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
}
Después de leer todas las publicaciones, se me ocurrió una solución integral para mostrar la descripción de la enumeración en la lista desplegable, así como seleccionar el valor adecuado del Modelo en la lista desplegable cuando se muestra en el modo de edición:
enumeración
using System.ComponentModel;
public enum CompanyType
{
[Description("")]
Null = 1,
[Description("Supplier")]
Supplier = 2,
[Description("Customer")]
Customer = 3
}
clase de extensión de enumeración:
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))
});
}
}
Clase de modelo
public class Company
{
public string CompanyName { get; set; }
public CompanyType Type { get; set; }
}
y vista:
@Html.DropDownListFor(m => m.Type,
@Model.Type.ToSelectList<CompanyType>())
y si está utilizando ese menú desplegable sin enlazar con el Modelo, puede usar esto en su lugar:
@Html.DropDownList("type",
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()}))
De este modo, puede esperar que su menú desplegable muestre Descripción en lugar de valores de enumeración. También cuando se trata de Editar, su modelo se actualizará mediante el valor seleccionado desplegable después de publicar la página.
Como ya lo han dicho otros, no te vincules a una enumeración, a menos que necesites unirte a diferentes enumeraciones según la situación. Hay varias maneras de hacer esto, un par de ejemplos a continuación.
ObjectDataSource
Una forma declarativa de hacerlo con ObjectDataSource. Primero, cree una clase de BusinessObject que devolverá la Lista para enlazar el DropDownList a:
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;
}
}
Luego, agregue alguna marca HTML a la página ASPX para que apunte a esta clase 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>
Esta opción no requiere ningún código detrás.
Código detrás de DataBind
Para minimizar el HTML en la página ASPX y enlazar en el Código Detrás:
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()));
}
}
}
De todos modos, el truco es dejar que los métodos de tipo Enum de GetValues, GetNames, etc., funcionen por usted.
No estoy seguro de cómo hacerlo en ASP.NET, pero echa un vistazo a este post ... ¿podría ayudar?
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);
}
Podrías usar 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();
public enum Color
{
RED,
GREEN,
BLUE
}
ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();
Después de encontrar esta respuesta, se me ocurrió lo que creo que es una forma mejor (al menos más elegante) de hacer esto, pensé que volvería y lo compartiría aquí.
Carga de página
DropDownList1.DataSource = Enum.GetValues(typeof(Response));
DropDownList1.DataBind();
LoadValues:
Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString();
Guardar valores:
Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text);
Código genérico utilizando la respuesta seis.
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();
}
Eso no es exactamente lo que estás buscando, pero podría ayudar:
http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx
Esta es probablemente una vieja pregunta ... pero así es como hice la mía.
Modelo:
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
}
Luego, en la Vista: aquí se explica cómo usar el menú desplegable.
@Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { @class = "form-control" })
Esto debería llenar todo en su lista de enumeración. Espero que esto ayude..
Desde entonces, ASP.NET se ha actualizado con algunas funciones más, y ahora puede usar la enumeración integrada para desplegar.
Si desea enlazar en el Enum mismo, use esto:
@Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response)))
Si está enlazando en una instancia de Respuesta, use esto:
// Assuming Model.Response is an instance of Response
@Html.EnumDropDownListFor(m => m.Response)
¿Por qué no usar así para poder pasar cada 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);
Si desea tener una descripción más fácil de usar en su cuadro combinado (u otro control), puede usar el atributo Descripción con la siguiente función:
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;
}
Aquí hay un ejemplo de una enumeración con atributos de descripción aplicados:
enum SampleEnum
{
NormalNoSpaces,
[Description("Description With Spaces")]
DescriptionWithSpaces,
[Description("50%")]
Percent_50,
}
Entonces enlazar para controlar como tal ...
m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum));
m_Combo_Sample.DisplayMember = "Value";
m_Combo_Sample.ValueMember = "Key";
De esta manera, puede colocar cualquier texto que desee en el menú desplegable sin que tenga que parecer un nombre de variable
Tutorial de asp.net y winforms con combobox y lista desplegable: Cómo usar Enum con Combobox en C # WinForms y Asp.Net
la esperanza ayuda
Revise mi publicación sobre la creación de un ayudante personalizado "ASP.NET MVC - Creación de un ayudante DropDownList para enumeraciones": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net -mvc-creating-a-dropdownlist-helper-for-enums.aspx
Esta es mi solución para Ordenar un Enum y DataBind (Texto y Valor) para desplegar usando 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()));
La solución aceptada no funciona, pero el siguiente código ayudará a otros a buscar la solución más corta.
foreach (string value in Enum.GetNames(typeof(Response)))
ddlResponse.Items.Add(new ListItem()
{
Text = value,
Value = ((int)Enum.Parse(typeof(Response), value)).ToString()
});
También puedes usar métodos de extensión. Para aquellos que no están familiarizados con las extensiones, sugiero revisar la documentación VB y C # .
Extensión 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
Para utilizar la extensión:
Imports <projectName>.CustomExtensions.ListItemCollectionExtension
...
yourDropDownList.Items.AddEnum(Of EnumType)()
Extensión 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")));
}
}
}
}
Para utilizar la extensión:
using CustomExtensions.ListItemCollectionExtension;
...
yourDropDownList.Items.AddEnum<EnumType>()
Si desea configurar el elemento seleccionado al mismo tiempo, reemplace
items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d")))
con
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)
Al convertir a System.Enum en lugar de evitar el tamaño int y los problemas de salida se evitan. Por ejemplo, 0xFFFF0000 sería 4294901760 como un uint pero sería -65536 como un int.
TryCast y System.Enum son un poco más rápidos que Convert.ChangeType (enumTypeValues [i], enumUnderType) .ToString () (12:13 en mis pruebas de velocidad).