it-swarm-es.tech

¿Cómo vincular un Enum a un control DropDownList en ASP.NET?

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?

117
Ray Vega

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);
}
106
Mark Glorie

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

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

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);
}
35
VanOrman
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
  }
22
user

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.

10
Amir Chatrbahr

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.

8
Johan Danforth

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

Enum.GetValues(typeof(Response));
6
rudigrobler
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);
}
5
Adarsh

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();
5
KrishnaDhungana
public enum Color
{
    RED,
    GREEN,
    BLUE
}

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

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);
3
Ben Hughes

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

}
3
Muhammed Qasim

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

1
roman m

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..

1
Marie McDonley

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)
1
bradlis7

¿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);
1
Mostafa

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

0
Josh Stribling

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

0
justin

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

0
Stuart Leeks

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()));
0
Diego Mendes

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

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

0
Trisped