it-swarm.it

Come associare un Enum a un controllo DropDownList in ASP.NET?

Diciamo che ho il seguente enum semplice:

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

Come posso associare questo enum a un controllo DropDownList in modo che le descrizioni vengano visualizzate nell'elenco e recuperare il valore numerico associato (1,2,3) dopo aver selezionato un'opzione?

118
Ray Vega

Probabilmente non vorrei legare i dati in quanto è un enum e non cambierà dopo il tempo di compilazione (a meno che non stia avendo uno di quei stoopid momenti).

Meglio solo iterare attraverso l'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

O lo stesso in 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);
}
107
Mark Glorie

Utilizzare la seguente classe di utilità Enumeration per ottenere un IDictionary<int,string> (Coppia Enum value & name) da un Enumeration; quindi associ IDictionary a un controllo associabile.

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

Esempio: Utilizzo della classe di utilità per associare i dati di enumerazione a un controllo

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

Lo uso per 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

La mia versione è solo una forma compressa di quanto sopra:

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
}

Ogni tipo di Enum deriva da System.Enum. Esistono due metodi statici che consentono di associare i dati a un controllo elenco a discesa (e recuperare il valore). Questi sono Enum.GetNames e Enum.Parse. Utilizzando GetNames, puoi associare il controllo del tuo elenco a discesa come segue:

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

Ora se vuoi il valore Enum Torna su Selezione ....

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

Dopo aver letto tutti i post ho trovato una soluzione completa per supportare la visualizzazione della descrizione dell'enum nell'elenco a discesa e la selezione del valore corretto dal Modello nel menu a discesa durante la visualizzazione in modalità Modifica:

enum:

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

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

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

classe di estensione 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 di modello:

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

e visualizza:

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

e se stai usando quel menu a discesa senza associarlo a Model, puoi invece usare questo:

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

Così facendo, puoi aspettarti che il tuo menu a discesa visualizzi la descrizione invece dei valori enum. Anche quando si tratta di Modifica, il modello verrà aggiornato dal valore a discesa selezionato dopo aver pubblicato la pagina.

10
Amir Chatrbahr

Come altri hanno già detto, non associare un database a un enum, a meno che non sia necessario associarsi a enum diversi a seconda della situazione. Esistono diversi modi per farlo, un paio di esempi di seguito.

ObjectDataSource

Un modo dichiarativo per farlo con ObjectDataSource. Innanzitutto, creare una classe BusinessObject che restituirà l'elenco per associare 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;
    }
}

Quindi aggiungere un markup HTML alla pagina ASPX per puntare a questa 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>

Questa opzione non richiede alcun codice dietro.

Code Behind DataBind

Per ridurre a icona il codice HTML nella pagina ASPX e associare 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()));
        }
    }
}

Comunque, il trucco è lasciare che i metodi di tipo Enum di GetValues, GetNames ecc. Funzionino per te.

8
Johan Danforth

Non sono sicuro di come farlo in ASP.NET ma dai un'occhiata questo post ... potrebbe aiutare?

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

Puoi usare 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

Dopo aver trovato questa risposta mi è venuto in mente quello che penso sia un modo migliore (almeno più elegante) di farlo, ho pensato di tornare e condividerlo qui.

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

Codice generico usando la risposta sei.

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

Questa è probabilmente una vecchia domanda .. ma è così che ho fatto la mia.

Modello:

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
}

Quindi nella vista: ecco come utilizzare popolare il menu a discesa.

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

Questo dovrebbe popolare tutto nella tua lista enum. Spero che sia di aiuto..

2
Marie McDonley

Non è proprio quello che stai cercando, ma potrebbe aiutare:

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

1
roman m

Da allora ASP.NET è stato aggiornato con alcune funzionalità aggiuntive e ora è possibile utilizzare l'enum integrato per il menu a discesa.

Se vuoi legare l'Enum stesso, usa questo:

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

Se stai vincolando un'istanza di Response, usa questo:

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

Perché non usarlo in questo modo per poter passare ogni elencoControle:


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 desideri avere una descrizione più user friendly nella tua casella combinata (o altro controllo) puoi usare l'attributo Descrizione con la seguente funzione:

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

Ecco un esempio di un enum con gli attributi Descrizione applicati:

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

Quindi vincola a controllare in questo modo ...

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

In questo modo puoi inserire tutto il testo che desideri nel menu a discesa senza che debba apparire come un nome di variabile

0
Josh Stribling

Tutorial su asp.net e winforms con combobox ed elenco a discesa: Come usare Enum con Combobox in C # WinForms e Asp.Net

la speranza aiuta

0
justin

Dai un'occhiata al mio post sulla creazione di un helper personalizzato "ASP.NET MVC - Creazione di un helper DropDownList per enum": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp net-MVC-creare-un-DropDownList-helper-per-enums.aspx

0
Stuart Leeks

Questa è la mia soluzione per ordinare un Enum e DataBind (testo e valore) al menu a discesa utilizzando 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 soluzione accettata non funziona, ma il codice seguente aiuterà gli altri a cercare la soluzione più breve.

 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

È inoltre possibile utilizzare i metodi di estensione. Per quelli che non hanno familiarità con le estensioni suggerisco di controllare la documentazione VB e C # .


Estensione 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

Per utilizzare l'estensione:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

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

Per utilizzare l'estensione:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

Se si desidera impostare contemporaneamente l'elemento selezionato, sostituirlo

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)

Convertendo in System.Enum invece si evitano problemi di dimensioni int e output. Ad esempio 0xFFFF0000 sarebbe 4294901760 come uint ma sarebbe -65536 come int.

TryCast e come System.Enum sono leggermente più veloci di Convert.ChangeType (enumTypeValues ​​[i], enumUnderType) .ToString () (12:13 nei miei test di velocità).

0
Trisped