84 votes

MVC3 Razor DropDownListFor Énumérations

Essayer de mettre à jour mon projet vers MVC3, quelque chose que je ne trouve tout simplement pas:

J'ai un simple type de données ENUMS:

public enum States()
{
  AL,AK,AZ,...WY
}

Que je veux utiliser comme liste déroulante/SelectList dans ma vue d'un modèle qui contient ce type de données:

public class FormModel()
{
    public States State {get; set;}
}

Plutôt simple: lorsque je vais utiliser la vue auto-générée pour cette classe partielle, elle ignore ce type.

J'ai besoin d'une liste déroulante simple qui définit la valeur de l'énumération comme l'élément sélectionné lorsque je clique sur soumettre et traite via ma méthode POST AJAX - JSON.

Et ensuite la vue (?!):

        @Html.DropDownListFor(model => model.State, model => model.States)

198voto

Mike McLaughlin Points 1841

J'ai trouvé une solution beaucoup plus simple pour cela ici: http://coding-in.net/asp-net-mvc-3-method-extension/

using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace EnumHtmlHelper.Helper
{    
    public static class EnumDropDownList
    {
        public static HtmlString EnumDropDownListFor(this HtmlHelper htmlHelper, Expression> modelExpression, string firstElement)
        {
            var typeOfProperty = modelExpression.ReturnType;
            if(!typeOfProperty.IsEnum)
                throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));     
            var enumValues = new SelectList(Enum.GetValues(typeOfProperty));
            return htmlHelper.DropDownListFor(modelExpression, enumValues, firstElement);
        }   
    }

Une ligne en razor le fera :

@Html.DropDownListFor(model => model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States))))

Vous pouvez également trouver du code pour le faire avec une méthode d'extension dans l'article lié.

55voto

jgauffin Points 51913

J'ai juste créé un pour mon propre projet. Le code ci-dessous fait partie de ma classe d'aide, j'espère avoir obtenu toutes les méthodes nécessaires. Écrivez un commentaire si cela ne fonctionne pas, et je vérifierai à nouveau.

public static class SelectExtensions
{

    public static string GetInputName(Expression> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor(this HtmlHelper htmlHelper, Expression> expression) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
    }

    public static SelectList ToSelectList(Type enumType, string selectedItem)
    {
        List items = new List();
        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
            var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
            var listItem = new SelectListItem
                {
                    Value = ((int)item).ToString(),
                    Text = title,
                    Selected = selectedItem == ((int)item).ToString()
                };
            items.Add(listItem);
        }

        return new SelectList(items, "Value", "Text", selectedItem);
    }
}

Utilisez-le comme suit :

Html.EnumDropDownListFor(m => m.YourEnum);

Mise à jour

J'ai créé des Html Helpers alternatifs. Tout ce que vous avez à faire pour les utiliser est de changer votre baseviewpage dans views\web.config.

Avec eux, vous pouvez simplement faire :

@Html2.DropDownFor(m => m.YourEnum);
@Html2.CheckboxesFor(m => m.YourEnum);
@Html2.RadioButtonsFor(m => m.YourEnum);

Plus d'informations ici : http://blog.gauffin.org/2011/10/first-draft-of-my-alternative-html-helpers/

24voto

Vincent Sels Points 321

À partir de ASP.NET MVC 5.1 (RC1), EnumDropDownListFor est inclus par défaut en tant que méthode d'extension de HtmlHelper.

17voto

stewartml Points 670

Si vous voulez quelque chose de vraiment simple, il y a une autre façon, selon la façon dont vous stockez l'état dans la base de données.

Si vous aviez une entité comme ceci :

public class Address
{
     //autres champs d'adresse

     //c'est ainsi que l'état est stocké dans la base de données
     public byte StateCode { get; set; }

     //cela mappe notre champ de base de données sur une énumération
     public States State
     {
         get
         {
             return (States)StateCode;
         }
         set
         {
             StateCode = (byte)value;
         }
     }
}

Alors la génération du menu déroulant serait aussi simple que ceci :

@Html.DropDownListFor(x => x.StateCode,
    from State state in Enum.GetValues(typeof(States))
    select new SelectListItem() { Text = state.ToString(), Value = ((int)state).ToString() }
);

Le LINQ n'est-il pas joli ?

12voto

JM1990 Points 78

J'ai pu faire cela en une seule ligne.

@Html.DropDownListFor(m=>m.VotrePropriete,new SelectList(Enum.GetValues(typeof(VotreTypeEnumeratif))))

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