Comment créer une dropdownlist à partir d'un enum dans ASP.NET MVC?

j'essaye d'utiliser la méthode d'extension Html.DropDownList mais je ne peux pas comprendre comment l'utiliser avec une énumération.

disons que j'ai une énumération comme celle-ci:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

comment créer une liste déroulante avec ces valeurs en utilisant la méthode d'extension Html.DropDownList ?

ou mon meilleur pari est-il de simplement créer une boucle pour et créer les éléments Html manuellement?

600
demandé sur Kevin Pang 2008-12-23 12:25:43

30 réponses

pour MVC v5.1 utiliser Html.Enumdropdownlist for

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

Pour MVC v5 utilisation EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

pour MVC 5 et inférieur

j'ai roulé Rune de réponse dans une extension de la méthode:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

cela vous permet d'écrire:

ViewData["taskStatus"] = task.Status.ToSelectList();

par using MyApp.Common

747
répondu Martin Faartoft 2016-08-26 02:22:20

je sais que je suis en retard à la fête sur ce sujet, mais j'ai pensé que vous pourriez trouver cette variante utile, car celle-ci vous permet également d'utiliser des chaînes descriptives plutôt que des constantes d'énumération dans la chute vers le bas. Pour ce faire, décorez chaque entrée de recensement 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);
    }

vous pouvez alors le faire dans votre vue:

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

J'espère que cela vous aidera!

**EDIT 2014-JAN-23: Microsoft viennent de publier MVC 5.1, qui dispose désormais d'une fonction EnumDropDownListFor. Malheureusement, il ne semble pas respecter l'attribut [Description] de sorte que le code ci-dessus tient toujours.Voir section Enum dans notes de version de Microsoft pour MVC 5.1.

mise à Jour: Il prend en charge le Affichage attribut [Display(Name = "Sample")] si, on peut donc l'utiliser.

[mise à Jour - juste remarqué cela, et le code ressemble à une version étendue de la code ici: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/ , avec quelques ajouts. Si tel est le cas, l'attribution paraît équitable ; -)]

340
répondu SimonGoldstone 2018-09-18 09:43:37

In ASP.NET MVC 5.1 , ils ont ajouté le EnumDropDownListFor() helper, donc pas besoin d'extensions personnalisées:

Modèle :

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

Vue :

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

utilisant L'aide D'étiquette (ASP.NET MVC 6) :

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
172
répondu Ofiris 2018-09-18 09:44:20

je suis tombé sur le même problème, j'ai trouvé cette question, et j'ai pensé que la solution fournie par Ash n'était pas ce que je cherchais; avoir à créer le HTML moi-même signifie moins de flexibilité par rapport à la fonction intégrée Html.DropDownList() .

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 vieux SelectList qui peut être utilisé comme vous êtes habitué à la vue:

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

le type anonyme et LINQ rend cela beaucoup plus élégant IMHO. Aucune infraction, l'intention, de la Cendre. :)

122
répondu Rune Jacobsen 2017-03-29 04:44:18

Voici une meilleure solution encapsulée:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

dites Voici votre modèle:

enter image description here

Exemple D'Utilisation:

enter image description here

UI générée: enter image description here

et généré HTML

enter image description here

Le Helper Code Source de l'Extension snap shot:

enter image description here

vous pouvez télécharger le projet échantillon à partir du lien que j'ai fourni.

EDIT: voici le code:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name="enumType">Type of the enum.</param>
    /// <param name="selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}
53
répondu Emran Hussain 2018-09-18 09:49:09

Html.DropDownListFor exige seulement un IEnumerable, ainsi une alternative à la solution de Prise est comme suit. Cela vous permettra d'écrire simplement:

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

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

en outre, vous n'avez pas vraiment besoin de généraliser la méthode d'extension que vous pouvez utiliser enumValue.GetType () plutôt que typeof (T).

modifier: solution ici aussi, et inclus la méthode d'extension ToDescription.

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();
    }
}
46
répondu Zaid Masud 2012-03-26 09:42:36

donc sans fonctions D'Extension si vous cherchez simple et facile.. C'est ce que j'ai fait

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

où XXXXX.Site.YYYY.Modèle.L'état est un enum

probablement mieux pour faire fonction d'aide, mais quand le temps est court cela fera le travail fait.

31
répondu Marty Trenouth 2010-10-26 17:13:06

pour étendre les réponses de Prise et de Rune, si vous souhaitez que l'attribut valeur de votre liste select soit associé à la valeur entière du type D'énumération, plutôt qu'à la valeur de chaîne, utilisez le code suivant:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

au lieu de traiter chaque valeur D'énumération comme un objet de TEnum, nous pouvons la traiter comme un objet et ensuite la lancer à l'entier pour obtenir la valeur non boxée.

Note: J'ai aussi ajouté un type générique contrainte pour restreindre les types pour lesquels cette extension est disponible aux seules structures (type de base D'Enum), et une validation de type d'exécution qui garantit que la structure transmise est bien un Enum.

mise à Jour 10/23/12: Ajout d'un paramètre de type générique pour le type sous-jacent et d'un problème de non-compilation fixe affectant .NET 4+.

21
répondu Nathan Taylor 2012-10-23 16:04:59

pour résoudre le problème d'obtenir le numéro au lieu du texte en utilisant la méthode d'extension de Prise.

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}
9
répondu ceedee 2010-06-02 21:48:03

une façon très facile de faire cela-sans tous les trucs d'extension qui semble exagérée est celle-ci:

votre enum:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

dans votre controller, liez L'Enum à une liste:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

après cela, jetez-le dans un sac de vue:

    ViewBag.RequiredLevel = new SelectList(myLevels);

finalement lient simplement à la vue:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

C'est de loin la façon la plus facile que j'ai trouvé et ne nécessite pas d'extensions ou quoi que ce soit d'aussi fou.

UPDATE : voir le commentaire de Andrews ci-dessous.

8
répondu Louie Bacaj 2015-04-29 22:28:07

la meilleure solution que j'ai trouvée pour cela était de combiner ce blog avec réponse de Simon Goldstone .

Cela permet l'utilisation d'enum dans le modèle. Essentiellement l'idée est d'utiliser une propriété integer aussi bien que l'enum, et émuler la propriété integer.

utiliser ensuite le [System.ComponentModel.Description] attribut pour annoter le modèle avec votre texte d'affichage, et utiliser un " EnumDropDownListFor" extension de votre point de vue.

cela rend à la fois la vue et le modèle très lisible et maintenable.

Modèle:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

Extension (directement à partir de Simon Goldstone la réponse de , inclus ici par souci d'exhaustivité):

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

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        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);
        }
    }
}
8
répondu Nick Evans 2018-09-18 09:50:05

vous voulez regarder l'utilisation de quelque chose comme Enum.GetValues

7
répondu Garry Shutler 2018-09-18 09:50:42
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
6
répondu Mr. Pumpkin 2014-01-24 00:53:33

ici Rune & Prise réponses modifiées pour utiliser la valeur Enum int comme ID.

Échantillon Enum:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}
"151970920 l'Extension de la méthode:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

exemple d'usage:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

N'oubliez pas D'importer l'espace de noms contenant la méthode D'Extension

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

Exemple de code HTML généré:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

noter que le point que vous utilisez pour appeler le ToSelectList sur l'élément sélectionné.

5
répondu Mr. Flibble 2011-12-01 12:23:03

C'est la version pour Rasoir:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)
4
répondu user550950 2011-12-12 06:52:12

maintenant cette fonctionnalité est prise en charge hors de la boîte dans MVC 5.1 à @Html.EnumDropDownListFor()

Vérifier le lien suivant:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

il est vraiment dommage qu'il ait fallu 5 ans à Microsoft pour mettre en œuvre une telle fonctionnalité qui est si en demande selon le vote ci-dessus!

4
répondu Lafi 2018-09-18 09:51:12

en S'appuyant sur la réponse de Simon, une approche similaire consiste à obtenir les valeurs Enum à afficher à partir d'un fichier de ressources, au lieu d'un attribut de description dans L'Enum lui-même. Ceci est utile si votre site doit être rendu dans plus d'une langue et si vous deviez avoir un fichier ressource spécifique pour Enums, vous pourriez aller un peu plus loin et avoir juste des valeurs Enum, dans votre Enum et les référencer à partir de l'extension par une convention telle que [EnumName]_[EnumValue] - en fin de compte moins de Dactylographie!

l'extension ressemble alors à:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

des Ressources dans les Énumérations.Le fichier Resx ressemble à ItemTypes_Movie: Film

une autre chose que j'aime faire est, au lieu d'appeler directement la méthode d'extension, je préfère l'appeler avec un @Html.EditorFor(x = > X. MyProperty), ou idéalement avoir juste la forme entière, dans un neat @Html.EditorForModel (). Pour ce faire, je change le modèle de chaîne de caractères pour ressembler à ceci

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

si cela vous intéresse, j'ai mis une réponse beaucoup plus détaillée ici sur mon blog:

http://paulthecyclist.com/2013/05/24/enum-dropdown /

3
répondu PaulTheCyclist 2013-05-24 19:52:16

Eh bien je suis vraiment en retard à la fête, mais pour ce que cela vaut, j'ai blogué sur ce sujet même par lequel je crée une classe EnumHelper qui permet une transformation très facile.

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

dans votre contrôleur:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

de votre point De Vue:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

La classe helper:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}
3
répondu NinjaNye 2013-11-08 12:44:00

je suis très en retard sur celui-ci, mais je viens de trouver une façon vraiment cool de le faire avec une ligne de code, si vous êtes heureux d'ajouter la mélodie non contrainte paquet NuGet (une belle, petite bibliothèque de Jon Skeet).

Cette solution est meilleure parce que:

  1. Il assure (avec le type générique, contraintes) que la valeur est une valeur d'enum (due à la Contrainte de la Mélodie)
  2. il évite inutile boxe (due à la Contrainte de la Mélodie)
  3. il cache toutes les descriptions pour éviter d'utiliser la réflexion sur chaque appel (en raison de la mélodie libre)
  4. C'est moins de code que les autres solutions!

Donc, voici les étapes pour obtenir ce travail:

  1. Dans Le Gestionnaire De Paquets De La Console, "Install-Package UnconstrainedMelody"
  2. Ajouter une propriété sur votre modèle comme:

    //Replace "YourEnum" with the type of your enum
    public IEnumerable<SelectListItem> AllItems
    {
        get
        {
            return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
        }
    }
    

maintenant que vous avez la liste de Sélectlistitem exposée sur votre modèle, vous pouvez utiliser le @Html.DropDownList ou @Html.Dropdownlistpour utiliser cette propriété comme source.

3
répondu nootn 2018-09-18 09:51:54

une autre correction à cette méthode d'extension - la version courante n'a pas sélectionné la valeur courante de l'enum. J'ai corrigé la dernière ligne:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }
2
répondu justabuzz 2010-10-10 01:27:31

si vous voulez ajouter le support de localisation, changez simplement le S. ToString () méthode à quelque chose comme ceci:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

ici la typeof(Resources) est la ressource que vous voulez charger, et ensuite vous obtenez la chaîne localisée, également utile si votre énumérateur a des valeurs avec des mots multiples.

2
répondu brafales 2010-11-12 12:09:18

C'est ma version de la méthode helper. J'utilise ceci:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

au lieu de cela:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

le voici:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }
2
répondu Vadim Sentiaev 2010-12-07 11:07:10

vous pouvez également utiliser mes Helpers HTML personnalisés dans Griffin.MvcContrib. Le code suivant:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

génère:

enter image description here

https://github.com/jgauffin/griffin.mvccontrib

2
répondu jgauffin 2011-10-28 08:29:48

j'ai trouvé une réponse ici . Cependant, certains de mes enums ont l'attribut [Description(...)] , donc j'ai modifié le code pour fournir le support pour cela:

    enum Abc
    {
        [Description("Cba")]
        Abc,

        Def
    }


    public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
    {
        IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
            .Cast<TEnum>();

        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var value in values)
        {
            string text = value.ToString();

            var member = typeof(TEnum).GetMember(value.ToString());
            if (member.Count() > 0)
            {
                var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (customAttributes.Count() > 0)
                {
                    text = ((DescriptionAttribute)customAttributes[0]).Description;
                }
            }

            items.Add(new SelectListItem
            {
                Text = text,
                Value = value.ToString(),
                Selected = (value.Equals(selectedValue))
            });
        }

        return htmlHelper.DropDownList(
            name,
            items
            );
    }

Espère que ça aide.

2
répondu Alkasai 2018-09-18 09:53:20

@Simon Goldstone: Merci pour votre solution, elle peut être parfaitement appliquée dans mon cas. Le seul problème, c'est que j'ai dû le traduire en VB. Mais maintenant c'est fait et pour sauver le temps des autres (au cas où ils en auraient besoin) je le mets ici:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .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 Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

fin vous l'utilisez comme ceci:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))
1
répondu Michal B. 2011-10-28 08:21:09

j'ai fini par créer des méthodes d'extension pour faire ce qui est essentiellement la réponse accepter ici. La dernière moitié du Gist traite spécifiquement D'Enum.

https://gist.github.com/3813767

1
répondu Nick Albrecht 2012-10-01 19:14:51
@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text="Male",Value="Male"},
 new ListItem{Text="Female",Value="Female"},
 new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)
1
répondu Shahnawaz 2013-05-30 10:10:44
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})
1
répondu vicky 2013-10-23 09:57:03

ici une variation de Martin Faartoft où vous pouvez mettre des étiquettes personnalisées qui est agréable pour la localisation.

public static class EnumHtmlHelper
{
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };

        return new SelectList(values, "Id", "Name", enumObj);
    }
}

utilisation en vue:

@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() { 
          { 1, ContactResStrings.FeedbackCategory }, 
          { 2, ContactResStrings.ComplainCategory }, 
          { 3, ContactResStrings.CommentCategory },
          { 4, ContactResStrings.OtherCategory }
      }), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)
1
répondu Rushino 2014-04-13 19:00:53

j'ai fait ce qui suit et travaille avec succès:

  • Dans la vue.cshtml:

@modèle Monmodèle.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • dans le modèle: Monmodèle.cs

public ItemTypes MyItemType { get; set; }

1
répondu MarwaAhmad 2016-03-13 17:50:16