web-dev-qa-db-fra.com

Comment liez-vous un enum à un contrôle DropDownList dans ASP.NET?

Disons que j'ai l'énumération simple suivante:

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

Comment puis-je lier cette énumération à un contrôle DropDownList afin que les descriptions soient affichées dans la liste ainsi que récupérer la valeur numérique associée (1, 2, 3) une fois qu'une option a été sélectionnée?

118
Ray Vega

Je ne voudrais probablement pas lier les données car c'est une énumération, et cela ne changera pas après le temps de compilation (sauf si j'ai un de ces stoopid moments).

Mieux vaut juste parcourir à travers l'énumération:

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 la même chose 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);
}
107
Mark Glorie

Utilisez la classe d’utilitaires suivante Enumeration pour obtenir un IDictionary<int,string> (Paire énumération valeur/nom) à partir de énumération; vous liez ensuite le IDictionary à un contrôle pouvant être lié.

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

Exemple: Utilisation de la classe d'utilitaires pour lier des données d'énumération à un contrôle

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

J'utilise ceci pour 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

Ma version est juste une forme compressée de ce qui précède:

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
}

Chaque type Enum dérive de System.Enum. Deux méthodes statiques permettent de lier des données à un contrôle de liste déroulante (et d'extraire la valeur). Ce sont Enum.GetNames et Enum.Parse. À l'aide de GetNames, vous pouvez vous connecter à votre contrôle de liste déroulante comme suit:

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

Maintenant, si vous voulez la valeur Enum Retour à la sélection ....

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

Après avoir lu tous les articles, je suis arrivé à une solution complète permettant d'afficher la description de l'énumération dans la liste déroulante et de sélectionner la valeur appropriée dans Modèle dans la liste déroulante lors de l'affichage en mode Édition:

enum:

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

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

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

classe d'extension 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 de modèle:

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

et voir:

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

et si vous utilisez cette liste déroulante sans être liée à Model, vous pouvez utiliser ceci à la place:

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

En faisant cela, vous pouvez vous attendre à ce que la liste déroulante affiche Description au lieu de valeurs enum. De plus, en ce qui concerne Edit, votre modèle sera mis à jour par la valeur sélectionnée après la page de publication.

10
Amir Chatrbahr

Comme d'autres l'ont déjà dit, ne vous associez pas à une enum, sauf si vous devez vous lier à d'autres enum en fonction de la situation. Il existe plusieurs façons de procéder, dont quelques exemples ci-dessous.

ObjectDataSource

Une façon déclarative de le faire avec ObjectDataSource. Commencez par créer une classe BusinessObject qui renverra la liste à lier à DropDownList:

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

Ajoutez ensuite des balises HTML à la page ASPX pour pointer vers cette 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>

Cette option ne nécessite aucun code derrière.

Code Behind DataBind

Pour minimiser le code HTML dans la page ASPX et le lier dans 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()));
        }
    }
}

Quoi qu'il en soit, l'astuce consiste à laisser les méthodes de type Enum de GetValues, GetNames, etc. travailler pour vous.

8
Johan Danforth

Je ne suis pas sûr de savoir comment le faire dans ASP.NET mais vérifiez this post ... cela pourrait aider?

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

Vous pouvez utiliser 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

Après avoir trouvé cette réponse, j’ai trouvé ce que je pense être une meilleure façon (au moins plus élégante) de le faire, mais j’ai pensé revenir ici et la partager.

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

Code générique utilisant la réponse six.

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

C'est probablement une vieille question .. mais c'est comme ça que j'ai fait la mienne.

Modèle:

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
}

Ensuite, dans la vue: voici comment utiliser le menu déroulant.

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

Cela devrait remplir tout dans votre liste enum. J'espère que cela t'aides..

2
Marie McDonley

Ce n'est pas tout à fait ce que vous cherchez, mais cela pourrait aider:

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

1
roman m

Depuis, ASP.NET a été mis à jour avec davantage de fonctionnalités. Vous pouvez maintenant utiliser l’énumération intégrée pour la liste déroulante.

Si vous voulez lier l'énum lui-même, utilisez ceci:

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

Si vous vous associez à une instance de Response, utilisez ceci:

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

Pourquoi ne pas utiliser comme ceci pour pouvoir passer chaque 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 vous souhaitez avoir une description plus conviviale dans votre liste déroulante (ou autre contrôle), vous pouvez utiliser l'attribut Description avec la fonction suivante:

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

Voici un exemple d'une énumération avec les attributs Description appliqués:

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

Ensuite, Liez pour contrôler comme si ...

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

De cette façon, vous pouvez mettre le texte que vous voulez dans le menu déroulant sans que celui-ci ne ressemble à un nom de variable.

0
Josh Stribling

Didacticiel asp.net et Winforms avec liste déroulante et liste déroulante: Comment utiliser Enum avec Combobox dans C # WinForms et Asp.Net

l'espoir aide

0
justin

Découvrez mon article sur la création d'un assistant personnalisé "ASP.NET MVC - Création d'un assistant DropDownList pour des énumérations": http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp -net-mvc-creation-a-dropdownlist-helper-for-enums.aspx

0
Stuart Leeks

Ceci est ma solution pour Order an Enum et DataBind (Text and Value) à Dropdown en utilisant 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 solution acceptée ne fonctionne pas, mais le code ci-dessous aidera les autres à la recherche de la solution la plus courte.

 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

Vous pouvez également utiliser des méthodes d'extension. Pour ceux qui ne connaissent pas les extensions, je suggère de vérifier la documentation VB et C # .


VB Extension:

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

Pour utiliser l'extension:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

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

Pour utiliser l'extension:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

Si vous souhaitez définir l’élément sélectionné en même temps, remplacez

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

avec

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)

En convertissant en System.Enum, on évite plutôt les problèmes de taille et de sortie int. Par exemple, 0xFFFF0000 correspondrait à 4294901760 en tant qu'uint mais à -65536 en tant qu'int.

TryCast et as System.Enum sont légèrement plus rapides que Convert.ChangeType (enumTypeValues ​​[i], enumUnderType) .ToString () (12:13 dans mes tests de vitesse).

0
Trisped