c# .net asp.net

c# - ¿Cómo se vincula un Enum a un control DropDownList en ASP.NET?



(24)

¿Por qué no usar así para poder pasar todas las listas? Controle:

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(); } Y el uso es tan simple como:

BindToEnum(typeof(NewsType), DropDownList1); BindToEnum(typeof(NewsType), CheckBoxList1); BindToEnum(typeof(NewsType), RadoBuuttonList1);

Digamos que tengo la siguiente enumeración simple:

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

¿Cómo puedo vincular 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?


Código genérico usando 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(); }


Como otros ya han dicho, no establezca un enlace de datos a una enumeración, a menos que deba vincularse a enumeraciones diferentes según la situación. Hay varias formas de hacerlo, un par de ejemplos a continuación.

ObjectDataSource

Una forma declarativa de hacerlo con ObjectDataSource. Primero, cree una clase BusinessObject que devolverá la Lista para vincular 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; } }

A continuación, agregue algunas marcas HTML a la página ASPX para apuntar 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 código detrás.

Código detrás de DataBind

Para minimizar el HTML en la página ASPX y vincular 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 el Enum escriba los métodos de GetValues, GetNames, etc. para que funcionen para usted.


Desde entonces, ASP.NET se ha actualizado con algunas funciones más, y ahora puede usar la enumeración incorporada al menú desplegable.

Si desea enlazar en el Enum, use esto:

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

Si está vinculando una instancia de Respuesta, use esto:

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


Después de encontrar esta respuesta, pensé en una forma mejor (al menos más elegante) de hacerlo, pensé en volver y compartirla aquí.

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


Después de leer todas las publicaciones, se me ocurrió una solución integral que permite mostrar la descripción enum en la lista desplegable y seleccionar el valor adecuado de la lista desplegable Modelo en el modo Edición:

enum:

using System.ComponentModel; public enum CompanyType { [Description("")] Null = 1, [Description("Supplier")] Supplier = 2, [Description("Customer")] Customer = 3 }

clase de extensión 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)) }); } }

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á usando ese menú desplegable sin vincularlo a Model, 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 enum. Además, cuando se trata de Editar, su modelo se actualizará mediante el valor desplegable seleccionado después de la publicación de la página.




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


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: a continuación 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..


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


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


No estoy seguro de cómo hacerlo en ASP.NET, pero echa un vistazo a this publicación ... ¿podría ayudar?

Enum.GetValues(typeof(Response));


Por alguna razón, la respuesta proporcionada por Mark Glorie no funcionó para mí. Como los GetValues ​​devuelven un objeto Array y no pude usar el indexer, obtiene el valor de sus elementos. Intenté itemsValue.GetValue (i) y funcionó, pero desafortunadamente no llenó el valor enum del valor del elemento de la lista desplegable. Acaba de llenar el nombre del elemento enum como el texto y el valor de la lista desplegable.

Modifiqué aún más el código de Mark y lo publiqué como la solución aquí. ¿Cómo vincular un Enum con su valor a DropDownList en ASP.NET?

Espero que esto ayude.

Gracias


Probablemente no uniría los datos ya que es una enumeración, y no cambiará después del tiempo de compilación (a menos que tenga uno de esos momentos de stoopid ).

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


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


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, }

Luego enlace para controlar como ...

m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum)); m_Combo_Sample.DisplayMember = "Value"; m_Combo_Sample.ValueMember = "Key";

De esta forma, puede colocar el texto que desee en el menú desplegable sin que tenga que parecer un nombre de variable


También puedes usar métodos de extensión. Para aquellos que no están familiarizados con las extensiones, sugiero consultar la documentación de VB y C# .

Extensión de 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 usar la extensión:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension ... yourDropDownList.Items.AddEnum(Of EnumType)()

Extensión de 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 usar la extensión:

using CustomExtensions.ListItemCollectionExtension; ... yourDropDownList.Items.AddEnum<EnumType>()

Si desea establecer 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, se evitan los problemas de tamaño interno y de salida. Por ejemplo, 0xFFFF0000 sería 4294901760 como una uint pero sería -65536 como int.

TryCast y como System.Enum son ligeramente más rápidos que Convert.ChangeType (enumTypeValues ​​[i], enumUnderType) .ToString () (12:13 en mis pruebas de velocidad).



Use la siguiente Enumeration clase de utilidad para obtener un IDictionary<int,string> (Enum value & name pair) de una Enumeración ; a continuación, vincula el IDictionary a un Control vinculable .

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


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


public enum Color { RED, GREEN, BLUE } ddColor.DataSource = Enum.GetNames(typeof(Color)); ddColor.DataBind();


public enum Color { RED, GREEN, BLUE }

Cada tipo de Enum deriva de System.Enum. Hay dos métodos estáticos que ayudan a vincular los 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 quiere que el valor de Enum vuelva a la selección ...

private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e) { Color selectedColor = (Color)Enum.Parse(ddColor.SelectedValue); }