737 votes

Comment créer un contrôle dropdownlist d’un enum dans ASP.NET MVC ?

Je suis en train d’utiliser la méthode d’extension Html.DropDownList mais ne peut pas savoir comment l’utiliser avec une énumération.

Disons que j’ai une énumération comme ceci :

Comment puis-je aller sur la création d’une liste déroulante avec ces valeurs à l’aide de la méthode d’extension Html.DropDownList ? Ou est mon meilleur pari de simplement créer un pour boucle et créer manuellement des éléments html ?

903voto

Martin Faartoft Points 3250

J’ai roulé réponse de Rune dans une méthode d’extension :

Cela vous permet d’écrire :

par``

375voto

SimonGoldstone Points 2901

Je sais je suis en retard à la fête, mais pensé que vous pourriez trouver cette variante utile, comme celle-ci vous permet également d'utiliser des chaînes descriptifs plutôt que de dénombrement des constantes dans la liste déroulante. Pour ce faire, décorer chaque énumération entrée avec un [Système.ComponentModel.Description] l'attribut.

Par exemple:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

Voici mon code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;

 ...

 private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        Type realModelType = modelMetadata.ModelType;

        Type underlyingType = Nullable.GetUnderlyingType(realModelType);
        if (underlyingType != null)
        {
            realModelType = underlyingType;
        }
        return realModelType;
    }

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        Type enumType = GetNonNullableModelType(metadata);
        IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

        IEnumerable<SelectListItem> items = from value in values
            select new SelectListItem
            {
                Text = GetEnumDescription(value),
                Value = value.ToString(),
                Selected = value.Equals(metadata.Model)
            };

        // If the enum is nullable, add an 'empty' item to the collection
        if (metadata.IsNullableValueType)
            items = SingleEmptyItem.Concat(items);

        return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    }

Ensuite, vous pouvez le faire dans votre vue:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

Espérons que cela vous aide!

EDITION 2014-JAN-23: Microsoft vient de publier MVC 5.1, qui a maintenant un EnumDropDownListFor fonctionnalité. Malheureusement, il ne semble pas respecter les [Description] l'attribut de sorte que le code ci-dessus est toujours debout. (Voir http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum pour Microsoft notes de mise à jour.)

Mise à jour: Il prend en charge la DisplyName attribut [Display(Name = "Sample")] , donc on peut l'utiliser.

[Mise à jour - juste remarqué cela, et le code ressemble à une version étendue de la code ici: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspxavec un couple d'ajouts. Si oui, l'attribution semble juste ;-)]

223voto

Ofiris Points 1659

Dans ASP.NET MVC 5.1, ils ont ajouté le `` d’assistance, pas besoin de pièces personnalisées :

Modèle:

Vue:

137voto

Rune Jacobsen Points 3621

Je suis tombé sur le même problème, trouve cette question, et de la pensée que la solution fournie par Ash n'était pas ce que je cherchais, d'Avoir à créer le code HTML de me signifie moins de flexibilité par rapport à la fonction intégrée dans le code Html.DropDownList() fonction.

S'avère C#3 etc. c'est assez facile. J'ai un Enum appelé TaskStatus:

var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
               select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);

Cela crée un bon ol' SelectList qui peuvent être utilisés comme vous êtes habitué à la vue:

<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>

Le type anonyme et LINQ qui rend ce beaucoup plus élégant à mon humble avis. Aucune infraction, l'intention, de la Cendre. :)

51voto

Zaid Masud Points 4536

Html.DropDownListFor ne nécessite qu'un IEnumerable, donc une alternative à la Prise de la solution est la suivante. Cela vous permettra d'écrire tout simplement:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[Où SelectedItemType est un domaine sur votre modèle de type ItemTypes, et votre modèle est non-null]

Aussi, vous n'avez pas vraiment besoin de genericize l'extension de la méthode que vous pouvez utiliser enumValue.GetType() plutôt que typeof(T).

EDIT: Intégré Simon solution ici, et inclus ToDescription méthode d'extension.

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

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