138 votes

Comment lier une Enum à un contrôle DropDownList en ASP.NET ?

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

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

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

11voto

Amir Chatrbahr Points 71

Après avoir lu tous les messages, j'ai trouvé une solution complète pour afficher la description de l'énumération dans la liste déroulante et pour sélectionner la valeur appropriée du 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 de l'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 View :

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

et si vous utilisez cette liste déroulante sans liaison avec le modèle, 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 procédant ainsi, vous pouvez vous attendre à ce que votre liste déroulante affiche des descriptions au lieu de valeurs d'énumération. De même, en ce qui concerne l'édition, votre modèle sera mis à jour par la valeur sélectionnée dans la liste déroulante après l'affichage de la page.

1 votes

Bien fait, surtout la partie avec les annotations [Description]. Je vais adopter cette technique.

0 votes

Explication soignée et propre. Kudos Amir !

8voto

Johan Danforth Points 1734

Comme d'autres l'ont déjà dit, n'établissez pas de liaison de données avec un enum, à moins que vous n'ayez besoin de vous lier à différents enums en fonction de la situation. Il y a plusieurs façons de faire cela, quelques exemples ci-dessous.

ObjectDataSource

Une façon déclarative de le faire avec ObjectDataSource. Tout d'abord, créez une classe BusinessObject qui renverra la liste à laquelle lier la 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 quelques 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 derrière DataBind

Pour minimiser le HTML dans la page ASPX et faire du bind in 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 (GetValues, GetNames, etc.) faire le travail pour vous.

7voto

rudigrobler Points 8883

Je ne suis pas sûr de savoir comment le faire en ASP.NET, mais jetez un coup d'œil à este post... ça pourrait aider ?

Enum.GetValues(typeof(Response));

7voto

KrishnaDhungana Points 2326

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

5voto

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X