Jak utworzyć dropdownlist z enum w ASP.NET MVC?

Próbuję użyć metody rozszerzenia Html.DropDownList, ale nie mogę rozgryźć, jak jej użyć przy wyliczaniu.

Powiedzmy, że mam takie Wyliczenie:

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

Jak utworzyć listę rozwijaną z tymi wartościami przy użyciu metody rozszerzenia Html.DropDownList?

A może najlepiej utworzyć pętlę for i ręcznie utworzyć elementy Html?

Author: Kevin Pang, 2008-12-23

30 answers

Dla MVC v5.1 Użyj Html.EnumDropDownListFor

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

Dla MVC v5 użyj EnumHelper

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

Dla MVC 5 i niższych

Zwinąłem odpowiedź Rune ' a do metody rozszerzenia:

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

To pozwala napisać:

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

By using MyApp.Common

 747
Author: Martin Faartoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-26 02:22:20

Wiem, że jestem spóźniony na przyjęcie w tej sprawie, ale pomyślałem, że ten wariant może okazać się przydatny, ponieważ ten pozwala również używać ciągów opisowych zamiast stałych wyliczeń w rozwijanej liście. Aby to zrobić, udekoruj każdy wpis wyliczenia znakiem [System.ComponentModel.Opis] atrybut.

Na przykład:

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

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

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

Oto Mój kod:

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

Możesz to zrobić według Ciebie:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)
Mam nadzieję, że to ci pomoże!

**EDIT 2014-JAN-23: Microsoft mają właśnie ukazał się MVC 5.1, który ma teraz funkcję EnumDropDownListFor. Niestety wydaje się, że nie respektuje atrybutu [Description], więc powyższy kod nadal stoi.Zobacz sekcję Enum w Uwagach do wydania Microsoft dla MVC 5.1.

Aktualizacja: obsługuje atrybut Display [Display(Name = "Sample")], więc można go używać.

[Update - właśnie to zauważyłem, a kod wygląda jak rozszerzona wersja kodu tutaj: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/, z kilkoma dodatkami. Jeśli tak, to przypisanie wydaje się sprawiedliwe; -)]

 340
Author: SimonGoldstone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:43:37

In ASP.NET MVC 5.1, dodali helpera EnumDropDownListFor(), więc nie ma potrzeby tworzenia własnych rozszerzeń:

Model :

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

widok :

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

Using Tag Helper (ASP.NET MVC 6):

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
 172
Author: Ofiris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:44:20

Wpadłem na ten sam problem, znalazłem to pytanie i pomyślałem, że rozwiązanie dostarczone przez Ash nie jest tym, czego szukałem; samodzielne tworzenie HTML oznacza mniejszą elastyczność w porównaniu do wbudowanej funkcji Html.DropDownList().

Okazuje się, że C # 3 itd. to ułatwia sprawę. Mam enum o nazwie 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);

To tworzy dobry ol ' SelectList, który może być używany jak jesteś przyzwyczajony do w widoku:

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

Anonimowy typ i LINQ sprawia, że jest to o wiele bardziej eleganckie IMHO. Bez obrazy, Ash. :)

 122
Author: Rune Jacobsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 04:44:18

Tutaj jest lepsze rozwiązanie:

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

Powiedz, że oto twój model:

Tutaj wpisz opis obrazka

Przykładowe Użycie:

Tutaj wpisz opis obrazka

Generowany interfejs użytkownika: Tutaj wpisz opis obrazka

I wygenerowany HTML

Tutaj wpisz opis obrazka

Kod źródłowy rozszerzenia pomocniczego snap shot:

Tutaj wpisz opis obrazka

Możesz pobrać przykładowy projekt z linku I pod warunkiem.

EDIT: Oto kod:

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
Author: Emran Hussain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:49:09

Html.DropDownListFor wymaga tylko liczby, więc alternatywą dla rozwiązania Prise jest następujący. To pozwoli Ci po prostu napisać:

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

[Gdzie SelectedItemType jest polem w modelu typu ItemTypes, a model nie jest null]

Poza tym, nie musisz generować metody rozszerzenia, ponieważ możesz użyć wartości enumValue.GetType () zamiast typeof (T).

EDIT: zintegrowane rozwiązanie Simona również tutaj i zawiera rozszerzenie opisów metoda.

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
Author: Zaid Masud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-26 09:42:36

Więc bez funkcji rozszerzenia, Jeśli szukasz prostego i łatwego.. This is what I did

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

Gdzie XXXXX.Miejsca.YYYY.Modelki.Stan jest enum

Prawdopodobnie lepiej wykonać funkcję pomocnika, ale gdy czas jest krótki, zadanie zostanie wykonane.

 31
Author: Marty Trenouth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-26 17:13:06

Rozszerzając odpowiedzi Prise i Rune, jeśli chcesz, aby atrybut value wybranych elementów listy mapował wartość całkowitą typu wyliczenia, zamiast wartości łańcuchowej, użyj następującego kodu:

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

Zamiast traktować każdą wartość wyliczenia jako obiekt TEnum, możemy traktować ją jako obiekt, a następnie wrzucić ją do liczby całkowitej, aby uzyskać wartość nieobsługiwaną.

Uwaga: Dodałem również ogólne ograniczenie typu, aby ograniczyć typy, dla których to rozszerzenie jest dostępne tylko dla struktur (typ bazowy Enum) oraz Walidacja typu run-time, która zapewnia, że przekazywana struktura jest rzeczywiście Enum.

Aktualizacja 10/23/12: Dodano parametr generic type dla bazowego typu i naprawiono problem bez kompilacji wpływający na. Net 4+.

 21
Author: Nathan Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 16:04:59

Aby rozwiązać problem uzyskania numeru zamiast tekstu za pomocą metody rozszerzenia 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
Author: ceedee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-02 21:48:03

Super łatwy sposób, aby to zrobić - bez tych wszystkich rozszerzeń, które wydają się przesadne, jest to:

Twoje enum:

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

Wewnątrz kontrolera połącz Enum z listą:

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

Potem wrzuć to do worka widokowego:

    ViewBag.RequiredLevel = new SelectList(myLevels);

W końcu po prostu połącz go z widokiem:

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

jest to zdecydowanie najprostszy sposób, jaki znalazłem i nie wymaga żadnych rozszerzeń ani niczego tak szalonego.

UPDATE : Zobacz komentarz poniżej.

 8
Author: Louie Bacaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 22:28:07

Najlepszym rozwiązaniem było połączenie tego bloga z odpowiedzi Simona Goldstone ' a.

Pozwala to na użycie enum w modelu. Zasadniczo chodzi o to, aby użyć właściwości integer, jak również enum i emulować właściwość integer.

Następnie użyj [System.ComponentModel.Opis] atrybut do dodawania adnotacji do modelu za pomocą wyświetlanego tekstu i używania rozszerzenia "EnumDropDownListFor"w widoku.

To sprawia, że zarówno Widok, jak i model bardzo czytelny i łatwy w utrzymaniu.

Model:

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

Widok:

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

Rozszerzenie (bezpośrednio z odpowiedzi Simona Goldstone ' a , dołączonej tutaj dla kompletności):

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
Author: Nick Evans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:50:05

Chcesz spojrzeć na używając czegoś takiego jak Enum.GetValues

 7
Author: Garry Shutler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:50:42
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
 6
Author: Mr. Pumpkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-24 00:53:33

To jest Rune & Prise odpowiedzi zmienione tak, aby używać wartości Enum int jako ID.

Przykładowe Wyliczenie:

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

Metoda rozszerzenia:

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

Próbka użycia:

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

Pamiętaj, aby zaimportować przestrzeń nazw zawierającą metodę rozszerzenia

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

Przykład wygenerowanego HTML:

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

Zauważ, że element, którego używasz do wywołania ToSelectList on, jest wybranym elementem.

 5
Author: Mr. Flibble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-01 12:23:03

To jest wersja dla Razor:

@{
    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
Author: user550950,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-12 06:52:12

Teraz ta funkcja jest obsługiwana od zaraz w MVC 5.1 do @Html.EnumDropDownListFor()

Sprawdź poniższy link:

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

To naprawdę wstyd, że zajęło Microsoftowi 5 lat, aby zaimplementować takie funkcje, które są tak pożądane zgodnie z powyższym głosowaniem!

 4
Author: Lafi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:51:12

Bazując na odpowiedzi Simona, podobnym podejściem jest wyświetlanie wartości Enum z pliku zasobu, zamiast w atrybucie opisu wewnątrz samego Enum. Jest to pomocne, jeśli Twoja witryna musi być renderowana w więcej niż jednym języku i jeśli chcesz mieć konkretny plik zasobów dla Enum, możesz pójść o krok dalej i mieć tylko wartości Enum, w swoim Enum i odwoływać się do nich z rozszerzenia za pomocą konwencji takiej jak [EnumName]_[EnumValue] - ostatecznie mniej pisanie!

Rozszerzenie wygląda wtedy następująco:

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

Zasoby w Enumach.Plik Resx wygląda jak ItemTypes_Movie: Film

Inną rzeczą, którą lubię robić, jest to, że zamiast wywoływać metodę rozszerzenia bezpośrednio, wolałbym wywołać ją za pomocą @Html.EditorFor (x => x. MyProperty), lub najlepiej po prostu mieć cały formularz, w jednym schludnym @Html.EditorForModel (). Aby to zrobić zmieniam szablon string, aby wyglądał tak

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

Jeśli cię to interesuje, umieściłem o wiele bardziej szczegółowe odpowiedz tutaj na moim blogu:

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

 3
Author: PaulTheCyclist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-24 19:52:16

Cóż, jestem naprawdę spóźniony na imprezę, ale jeśli to coś warte, napisałem na blogu o tym właśnie temacie, w którym tworzę EnumHelper klasę, która umożliwia bardzo łatwą transformację.

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

W Twoim kontrolerze:

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

Według ciebie:

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

Klasa pomocnicza:

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
Author: NinjaNye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-08 12:44:00

Jestem bardzo spóźniony, ale znalazłem naprawdę fajny sposób, aby to zrobić z jedną linijką kodu, jeśli jesteś szczęśliwy, aby dodać Unstrained Melody pakiet NuGet (ładna, mała biblioteka od Jona Skeeta).

To rozwiązanie jest lepsze ponieważ:

  1. zapewnia (z ograniczeniami typu ogólnego), że wartość rzeczywiście jest wartością enum (ze względu na nieograniczoną melodię)
  2. unika niepotrzebnego boksu (ze względu na nieskrępowaną melodię)
  3. buforuje wszystkie opisy aby uniknąć używania refleksji przy każdym wywołaniu (ze względu na nieskrępowaną melodię)
  4. to mniej kodu niż inne rozwiązania!

Oto kroki, aby to zadziałało:

  1. W Konsoli Menedżera Pakietów, "Install-Package Unstrained"
  2. Dodaj nieruchomość na swoim modelu w ten sposób:

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

Teraz, gdy masz listę SelectListItem na swoim modelu, możesz użyć @Html.DropDownList lub @ Html.Dropdownlistdla korzystania z tej właściwości jako źródło.

 3
Author: nootn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:51:54

Kolejna poprawka do tej metody rozszerzenia - bieżąca wersja nie wybrała bieżącej wartości enum. Poprawiłem ostatnią linijkę:

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
Author: justabuzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-10 01:27:31

Jeśli chcesz dodać obsługę lokalizacji po prostu zmień metodę s.toString () na coś takiego:

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

Tutaj typeof (Resources) jest zasobem, który chcesz załadować, a następnie otrzymasz zlokalizowany ciąg znaków, również przydatny, jeśli twój enumerator ma wartości z wieloma słowami.

 2
Author: brafales,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 12:09:18

To jest moja wersja metody helper. Używam tego:

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

Zamiast tego:

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

Oto jest:

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
Author: Vadim Sentiaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-07 11:07:10

Możesz również użyć my custom HtmlHelpers w Griffin.MvcContrib. Następujący kod:

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

Generuje:

Tutaj wpisz opis obrazka

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

 2
Author: jgauffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 08:29:48

Znalazłem odpowiedź TUTAJ . Jednak niektóre moje liczby mają atrybut [Description(...)], więc zmodyfikowałem kod, aby zapewnić wsparcie dla tego:

    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
            );
    }
Mam nadzieję, że to pomoże.
 2
Author: Alkasai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-18 09:53:20

@Simon Goldstone: dzięki za rozwiązanie, w moim przypadku można je idealnie zastosować. Jedynym problemem jest to, że musiałem przetłumaczyć to na VB. Ale teraz jest zrobione i aby zaoszczędzić czas innych ludzi (w razie potrzeby) umieściłem go tutaj:

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

Koniec używaj go tak:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))
 1
Author: Michal B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-28 08:21:09

Skończyło się na stworzeniu metod rozszerzania, aby zrobić to, co jest zasadniczo Akceptuj odpowiedź tutaj. Ostatnia połowa Gist dotyczy konkretnie Enum.

Https://gist.github.com/3813767

 1
Author: Nick Albrecht,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Shahnawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: vicky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 09:57:03

Oto odmiana Martina Faartofta, w której można umieścić niestandardowe etykiety, które są miłe dla lokalizacji.

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

Użycie w widoku:

@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
Author: Rushino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-13 19:00:53

Zrobiłem następujące i działa pomyślnie:

  • w widoku.cshtml:

@model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • w modelu: MyModel.cs

public ItemTypes MyItemType { get; set; }

 1
Author: MarwaAhmad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-13 17:50:16