ti-enxame.com

Como você liga um Enum a um controle DropDownList no ASP.NET?

Digamos que eu tenha o seguinte enum simples:

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

Como posso vincular esse enum a um controle DropDownList para que as descrições sejam exibidas na lista, bem como recuperar o valor numérico associado (1,2,3) uma vez que uma opção tenha sido selecionada?

117
Ray Vega

Eu provavelmente não iria vincular os dados, pois é um enum, e não vai mudar após o tempo de compilação (a menos que eu esteja tendo um desses stoopid momentos).

Melhor apenas para percorrer o enum:

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

Ou o mesmo em 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 a seguinte classe de utilitário Enumeration para obter um IDictionary<int,string> (valor Enum & par de nomes) de um Enumeration; você então liga o IDictionary a um Controle ligável.

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

Exemplo: Usando a classe de utilitário para ligar dados de enumeração a um controle

ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField = "Value";
ddlResponse.DataValueField = "Key";
ddlResponse.DataBind();
69
Leyu

Eu uso isso 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

Minha versão é apenas uma forma comprimida dos itens acima:

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. Existem dois métodos estáticos que ajudam a vincular dados a um controle de lista suspensa (e recuperar o valor). Estes são Enum.GetNames e Enum.Parse. Usando GetNames, você é capaz de vincular ao seu controle de lista suspensa da seguinte maneira:

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

Agora, se você quiser o valor Enum Back on Selection ....

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

Depois de ler todas as postagens, desenvolvi uma solução abrangente para oferecer suporte à exibição da descrição do enum na lista suspensa, além de selecionar o valor adequado no menu suspenso Model in ao exibir no modo Edit:

enum:

using System.ComponentModel;
public enum CompanyType
{
    [Description("")]
    Null = 1,

    [Description("Supplier")]
    Supplier = 2,

    [Description("Customer")]
    Customer = 3
}

classe de extensão 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))
                          });
    }
}

Classe do modelo:

public class Company
{
    public string CompanyName { get; set; }
    public CompanyType Type { get; set; }
}

e Visualizar:

@Html.DropDownListFor(m => m.Type,
@Model.Type.ToSelectList<CompanyType>())

e se você estiver usando esse menu suspenso sem vincular-se ao Modelo, poderá usar isso:

@Html.DropDownList("type",                  
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()}))

Portanto, ao fazer isso, você pode esperar que sua lista suspensa exiba Descrição em vez de valores de enumeração. Além disso, quando se trata de Editar, seu modelo será atualizado pelo valor selecionado da lista suspensa após a página de postagem.

11
Amir Chatrbahr

Como outros já disseram - não vincular a um enum, a menos que você precise vincular enums diferentes, dependendo da situação. Existem várias maneiras de fazer isso, alguns exemplos abaixo.

ObjectDataSource

Uma maneira declarativa de fazer isso com ObjectDataSource. Primeiro, crie uma classe BusinessObject que retornará a lista para ligar o 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;
    }
}

Em seguida, adicione alguma marcação HTML à página ASPX para apontar para esta classe 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 opção não requer nenhum código por trás.

Code Behind DataBind

Para minimizar o HTML na página ASPX e vincular em 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()));
        }
    }
}

De qualquer forma, o truque é permitir que os métodos do tipo Enum de GetValues, GetNames etc. funcionem para você.

8
Johan Danforth

Não tenho certeza como fazê-lo no asp.net, mas confira this post ... pode ajudar?

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

Você poderia usar o 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

Depois de encontrar essa resposta, descobri o que eu acho ser uma maneira melhor (pelo menos mais elegante) de fazer isso, pensei em voltar e compartilhar isso aqui.

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

Código genérico usando a resposta 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

Isso não é exatamente o que você está procurando, mas pode ajudar:

http://blog.jeffhandley.com/archive/2008/01/27/enum-list-dropdown-control.aspx

1
roman m

Esta é provavelmente uma questão antiga ... mas é assim que eu fiz o meu.

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
}

Em seguida, na visualização: veja como usar o menu suspenso.

@Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { @class = "form-control" })

Isso deve preencher tudo na sua lista de enumeração. Espero que isto ajude..

1
Marie McDonley

O ASP.NET já foi atualizado com mais algumas funcionalidades, e agora você pode usar o enum interno para o menu suspenso.

Se você quiser ligar o próprio Enum, use isto:

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

Se você estiver vinculando uma instância de Response, use isto:

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

Por que não usar assim para poder passar cada listaControle:


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

Se você gostaria de ter uma descrição mais amigável em sua caixa de combinação (ou outro controle), você pode usar o atributo Descrição com a seguinte função:

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

Aqui está um exemplo de um enum com atributos Description aplicados:

    enum SampleEnum
    {
        NormalNoSpaces,
        [Description("Description With Spaces")]
        DescriptionWithSpaces,
        [Description("50%")]
        Percent_50,
    }

Então Bind to control like so ...

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

Dessa forma, você pode colocar qualquer texto que desejar no menu suspenso sem que ele tenha que se parecer com um nome de variável

0
Josh Stribling

Ambos asp.net e winforms tutorial com combobox e dropdownlist: Como usar Enum com Combobox em c # WinForms e Asp.Net

esperança ajuda

0
justin

Confira meu post sobre como criar um ajudante personalizado "ASP.NET MVC - Criando um ajudante DropDownList para enums": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp -net-mvc-criando-um-dropdownlist-helper-for-enums.aspx

0
Stuart Leeks

Esta é a minha solução para Solicitar um Enum e DataBind (Texto e Valor) para o Dropdown usando o 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

A solução aceita não funciona, mas o código abaixo ajudará outras pessoas procurando a solução mais curta.

 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

Você também pode usar métodos de extensão. Para aqueles que não estão familiarizados com extensões, sugiro verificar a documentação VB e C # .


Extensão 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 a extensão:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

Extensão 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 a extensão:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

Se você quiser definir o item selecionado ao mesmo tempo, substitua

items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d")))

com

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)

Ao converter para System.Enum, em vez disso, o tamanho int e os problemas de saída são evitados. Por exemplo, 0xFFFF0000 seria 4294901760 como um uint, mas seria -65536 como um int.

TryCast e como System.Enum são ligeiramente mais rápidos que Convert.ChangeType (enumTypeValues ​​[i], enumUnderType) .ToString () (12:13 nos meus testes de velocidade).

0
Trisped