it-swarm.com.de

Wie erstellen Sie eine Dropdown-Liste aus einer Aufzählung in ASP.NET MVC?

Ich versuche, die Erweiterungsmethode Html.DropDownList zu verwenden, kann aber nicht herausfinden, wie sie mit einer Aufzählung verwendet wird.

Nehmen wir an, ich habe eine Aufzählung wie diese:

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

Wie erstelle ich ein Dropdown-Menü mit diesen Werten mithilfe der Erweiterungsmethode Html.DropDownList?

Oder ist es meine beste Wahl, einfach eine for-Schleife zu erstellen und die HTML-Elemente manuell zu erstellen?

644
Kevin Pang

Verwenden Sie für MVC v5.1 Html.EnumDropDownListFor

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

Verwenden Sie für MVC v5 EnumHelper

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

Für MVC 5 und niedriger

Ich habe Runes Antwort in eine Erweiterungsmethode gerollt:

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

So können Sie schreiben:

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

von using MyApp.Common

808
Martin Faartoft

Ich weiß, dass ich zu spät zur Party komme, aber ich dachte, Sie finden diese Variante vielleicht nützlich, da Sie hier auch beschreibende Zeichenfolgen anstelle von Aufzählungskonstanten in der Dropdown-Liste verwenden können. Verzieren Sie dazu jeden Aufzählungseintrag mit einem Attribut [System.ComponentModel.Description].

Zum Beispiel:

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

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

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

Hier ist mein 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);
    }

Sie können dies dann aus Ihrer Sicht tun:

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

Hoffe das hilft dir!

** BEARBEITEN 2014-JAN-23: Microsoft hat gerade MVC 5.1 veröffentlicht, das jetzt über eine EnumDropDownListFor-Funktion verfügt. Leider scheint das Attribut [Description] nicht berücksichtigt zu werden, sodass der obige Code weiterhin gültig ist. Siehe Abschnitt Enum in Microsoft-Versionshinweise für MVC 5.1.

Update: Es unterstützt das Display Attribut [Display(Name = "Sample")], also kann man das benutzen.

[Update - habe dies gerade bemerkt und der Code sieht aus wie eine erweiterte Version des Codes hier: https://blogs.msdn.Microsoft.com/stuartleeks/2010/05/21/asp-net-mvc- Erstellen einer Dropdown-Liste-Helfer-für-Aufzählungen / , mit ein paar Ergänzungen. Wenn ja, erscheint die Zuschreibung fair ;-)]

350
SimonGoldstone

In ASP.NET MVC 5.1 wurde der EnumDropDownListFor() -Hilfer hinzugefügt, sodass keine benutzerdefinierten Erweiterungen erforderlich sind:

Modell :

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

Ansicht :

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

Verwenden von Tag Helper (ASP.NET MVC 6) :

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">
187
Ofiris

Ich bin auf dasselbe Problem gestoßen, habe diese Frage gefunden und dachte, dass die Lösung von Ash nicht das ist, wonach ich gesucht habe. Das HTML selbst erstellen zu müssen, bedeutet weniger Flexibilität als die eingebaute Funktion Html.DropDownList().

Es stellte sich heraus, dass C # 3 usw. dies ziemlich einfach macht. Ich habe ein enum mit dem Namen 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);

Dadurch wird ein gutes altes SelectList erstellt, das so verwendet werden kann, wie Sie es in der Ansicht gewohnt sind:

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

Die anonyme Art und LINQ macht dies IMHO so viel eleganter. Nichts für ungut, Ash. :)

127
Rune Jacobsen

Hier ist eine besser gekapselte Lösung:

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

Angenommen, hier ist Ihr Modell:

enter image description here

Beispielnutzung:

enter image description here

Generierte Benutzeroberfläche:  enter image description here

und generiertes HTML

enter image description here

Die Momentaufnahme des Quellcodes der Helper-Erweiterung:

enter image description here

Sie können das Beispielprojekt über den von mir bereitgestellten Link herunterladen.

EDIT: Hier ist der 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();
    }
}
60
Emran Hussain

Für Html.DropDownListFor ist nur ein IEnumerable erforderlich. Eine Alternative zu Prises Lösung lautet daher wie folgt. So können Sie einfach schreiben:

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

[Wobei SelectedItemType ein Feld in Ihrem Modell vom Typ ItemTypes ist und Ihr Modell nicht null ist]

Außerdem müssen Sie die Erweiterungsmethode nicht wirklich generieren, da Sie enumValue.GetType () anstelle von typeof (T) verwenden können.

BEARBEITEN: Integrierte auch hier die Lösung von Simon und integrierte die ToDescription-Erweiterungsmethode.

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

Also ohne Extension-Funktionen, wenn Sie einfach und unkompliziert suchen .. Das habe ich getan

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

dabei ist XXXXX.Sites.YYYY.Models.State eine Aufzählung

Wahrscheinlich ist es besser, die Helferfunktion auszuführen, aber wenn die Zeit knapp ist, wird dies die Arbeit erledigen.

32
Marty Trenouth

Wenn Sie möchten, dass das value-Attribut Ihrer Auswahllistenelemente dem ganzzahligen Wert des Aufzählungstyps und nicht dem Zeichenfolgenwert zugeordnet wird, verwenden Sie den folgenden Code, um die Antworten von Prize und Rune zu erweitern:

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

Anstatt jeden Aufzählungswert als TEnum-Objekt zu behandeln, können wir ihn als Objekt behandeln und ihn dann in eine Ganzzahl umwandeln, um den Wert ohne Box zu erhalten.

Anmerkung: Ich habe auch eine generische Typeinschränkung hinzugefügt, um die Typen, für die diese Erweiterung verfügbar ist, nur auf Strukturen (Enums Basistyp) zu beschränken, und eine Laufzeit-Typüberprüfung, die sicherstellt, dass die übergebene Struktur gültig ist in der Tat eine Aufzählung.

pdate 23.10.12: Generischer Typparameter für zugrunde liegenden Typ hinzugefügt und Nicht-Kompilierungsproblem behoben, das .NET 4+ betrifft.

22
Nathan Taylor

Die beste Lösung, die ich dafür gefunden habe, war dieses Blog mit Simon Goldstones Antwort zu kombinieren.

Dies ermöglicht die Verwendung der Aufzählung im Modell. Im Wesentlichen besteht die Idee darin, eine Ganzzahleigenschaft sowie die Aufzählung zu verwenden und die Ganzzahleigenschaft zu emulieren.

Verwenden Sie dann das Attribut [System.ComponentModel.Description], um das Modell mit Ihrem Anzeigetext zu versehen, und verwenden Sie in Ihrer Ansicht die Erweiterung "EnumDropDownListFor".

Dies macht sowohl die Ansicht als auch das Modell sehr gut lesbar und wartbar.

Modell:

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

Aussicht:

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

Erweiterung (direkt von Antwort von Simon Goldstone , der Vollständigkeit halber hier eingeschlossen):

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);
        }
    }
}
10
Nick Evans

Lösen des Problems, dass die Nummer anstelle von Text mithilfe der Prise-Erweiterungsmethode abgerufen wird.

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

Ein super einfacher Weg, dies zu erledigen - ohne all das Erweiterungsmaterial, das übertrieben zu sein scheint, ist dieser:

Ihre Aufzählung:

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

Binden Sie die Enumeration in Ihrem Controller an eine Liste:

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

Danach werfen Sie es in einen ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

Schließlich binden Sie es einfach an die Ansicht:

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

Dies ist bei weitem der einfachste Weg, den ich gefunden habe, und erfordert keine Erweiterungen oder etwas Verrücktes.

UPDATE: Siehe Andrews Kommentar unten.

9
Louie Bacaj

Sie möchten etwas wie Enum.GetValues verwenden

8
Garry Shutler
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
7
Mr. Pumpkin

Dies sind Rune & Prize-Antworten, die so geändert wurden, dass der Wert Enum int als ID verwendet wird.

Beispiel Enum:

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

Verlängerungsmethode:

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

Anwendungsbeispiel:

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

Denken Sie daran, den Namespace zu importieren, der die Extension-Methode enthält

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

Beispiel für generiertes HTML:

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

Beachten Sie, dass das Element, mit dem Sie ToSelectList aufrufen, das ausgewählte Element ist.

6
Mr. Flibble

Dies ist die Version für 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)
5
user550950

Diese Funktion wird ab sofort in MVC 5.1 über @Html.EnumDropDownListFor() unterstützt.

Überprüfen Sie den folgenden Link:

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

Es ist wirklich schade, dass Microsoft 5 Jahre gebraucht hat, um ein solches Feature zu implementieren, das laut obiger Abstimmung so gefragt ist!

5
Lafi

Nun, ich bin wirklich zu spät zur Party, aber für das, was es wert ist, habe ich über genau dieses Thema gebloggt, wobei ich eine EnumHelper -Klasse erstelle, die eine sehr einfache Transformation ermöglicht.

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

In Ihrem Controller:

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

Ihrer Ansicht nach:

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

Die Hilfsklasse:

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

Aufbauend auf der Antwort von Simon besteht ein ähnlicher Ansatz darin, die Enum-Werte aus einer Ressourcendatei anstelle eines Beschreibungsattributs in der Enum-Datei selbst anzuzeigen. Dies ist hilfreich, wenn Ihre Website in mehr als einer Sprache gerendert werden muss und wenn Sie eine bestimmte Ressourcendatei für Enums haben, können Sie noch einen Schritt weiter gehen und nur Enum-Werte in Ihrer Enum-Datei haben und sie aus der Erweiterung von referenzieren eine Konvention wie [EnumName] _ [EnumValue] - letztendlich weniger tippen!

Die Erweiterung sieht dann so aus:

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

Ressourcen in der Enums.Resx-Datei sehen aus wie ItemTypes_Movie: Film

Eine andere Sache, die ich gerne mache, ist, anstatt die Erweiterungsmethode direkt aufzurufen, sie lieber mit einem @ Html.EditorFor (x => x.MyProperty) aufzurufen oder im Idealfall nur die gesamte Form in einem ordentlichen @ zu haben. Html.EditorForModel (). Dazu ändere ich das String Template so, dass es so aussieht

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

Wenn dich das interessiert, habe ich hier auf meinem Blog eine viel ausführlichere Antwort veröffentlicht:

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

4
PaulTheCyclist

Ich bin sehr spät dran, aber ich habe gerade einen wirklich coolen Weg gefunden, dies mit einer Codezeile zu tun, wenn Sie glücklich sind, das Paket nconstrained Melody NuGet (eine nette, kleine Bibliothek von Jon) hinzuzufügen Skeet).

Diese Lösung ist besser, weil:

  1. Es stellt (mit generischen Typeinschränkungen) sicher, dass der Wert wirklich ein Aufzählungswert ist (aufgrund von Melodie ohne Einschränkung).
  2. Es vermeidet unnötiges Boxen (aufgrund der uneingeschränkten Melodie)
  3. Es werden alle Beschreibungen zwischengespeichert, um zu vermeiden, dass bei jedem Anruf eine Reflektion verwendet wird (aufgrund der uneingeschränkten Melodie).
  4. Es ist weniger Code als die anderen Lösungen!

Also, hier sind die Schritte, um dies zum Laufen zu bringen:

  1. In der Package Manager-Konsole "Install-Package UnconstrainedMelody"
  2. Fügen Sie Ihrem Modell eine Eigenschaft wie folgt hinzu:

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

Nachdem Sie die Liste von SelectListItem in Ihrem Modell verfügbar gemacht haben, können Sie die @ Html.DropDownList oder @ Html.DropDownListF verwenden, um diese Eigenschaft als Quelle zu verwenden.

3
nootn

Ich habe eine Antwort gefunden hier . Einige meiner Aufzählungen haben jedoch das Attribut [Description(...)], daher habe ich den Code geändert, um dies zu unterstützen:

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

Ich hoffe, das hilft.

3
Alkasai

In .NET Core können Sie einfach Folgendes verwenden:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())
3
GoldenAge

Sie können auch meine benutzerdefinierten HtmlHelper in Griffin.MvcContrib verwenden. Der folgende Code:

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

Erzeugt:

enter image description here

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

2
jgauffin

Wenn Sie die Lokalisierungsunterstützung hinzufügen möchten, ändern Sie einfach die s.toString () -Methode in etwa wie folgt:

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

In diesem Beispiel ist typeof (Resources) die Ressource, die Sie laden möchten. Anschließend erhalten Sie die lokalisierte Zeichenfolge. Dies ist auch nützlich, wenn Ihr Enumerator Werte mit mehreren Wörtern enthält.

2
brafales

Dies ist meine Version der Hilfsmethode. Ich benutze das:

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

Stattdessen:

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

Hier ist es:

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
Vadim Sentiaev

Ein weiterer Fix für diese Erweiterungsmethode: In der aktuellen Version wurde der aktuelle Wert der Aufzählung nicht ausgewählt. Ich habe die letzte Zeile gefixt:

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
justabuzz

Ich möchte diese Frage auf eine andere Weise beantworten, bei der der Benutzer nichts in den Ausdrücken controller oder Linq tun muss. Diesen Weg...

Ich habe ein ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

Jetzt kann ich einfach ein dropdown erstellen, indem ich dieses enum verwende.

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

OR

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

Wenn Sie einen Index auswählen möchten, versuchen Sie dies

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

Hier habe ich AccessLevelEnum.NoAccess als zusätzlichen Parameter für die Standardauswahl des Dropdowns verwendet.

1
gdmanandamohon
@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
vicky
@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
Shahnawaz

Am Ende habe ich Erweiterungsmethoden erstellt, um das zu tun, was hier im Wesentlichen die akzeptierte Antwort ist. Die letzte Hälfte der Gist befasst sich speziell mit Enum.

https://Gist.github.com/3813767

1
Nick Albrecht

Hier eine Martin Faartoft-Variante, in der Sie benutzerdefinierte Beschriftungen anbringen können, die sich gut zur Lokalisierung eignen.

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

In Ansicht verwenden:

@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
Rushino
        ////  ViewModel

        public class RegisterViewModel
          {

        public RegisterViewModel()
          {
              ActionsList = new List<SelectListItem>();
          }

        public IEnumerable<SelectListItem> ActionsList { get; set; }

        public string StudentGrade { get; set; }

           }

       //// Enum Class

        public enum GradeTypes
             {
               A,
               B,
               C,
               D,
               E,
               F,
               G,
               H
            }

         ////Controller action 

           public ActionResult Student()
               {
    RegisterViewModel vm = new RegisterViewModel();
    IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
                                         .Cast<GradeTypes>();                  
    vm.ActionsList = from action in actionTypes
                     select new SelectListItem
                     {
                         Text = action.ToString(),
                         Value = action.ToString()
                     };
              return View(vm);
               }

         ////// View Action

   <div class="form-group">
                            <label class="col-lg-2 control-label" for="hobies">Student Grade:</label>
                            <div class="col-lg-10">
                               @Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
                            </div>
1
shuvo sarker

In MVC4 würde ich das gerne machen

@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })

public enum RefType
    {
        Web = 3,
        API = 4,
        Security = 5,
        FE = 6
    }

    public class Reference
    {
        public int Id { get; set; }
        public RefType RefType { get; set; }
    }
1

Ich habe folgendes gemacht und arbeite erfolgreich:

  • In der view.cshtml:

@model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • Im Modell: MyModel.cs

public ItemTypes MyItemType { get; set; }

1
MarwaAhmad

@ Simon Goldstone: Danke für deine Lösung, sie kann in meinem Fall perfekt angewendet werden. Das einzige Problem ist, dass ich es in VB übersetzen musste. Aber jetzt ist es geschafft und um anderen Zeit zu sparen (falls sie es brauchen), habe ich es hier abgelegt:

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

Ende Du verwendest es so:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))
1
Michal B.

1- Erstellen Sie Ihre ENUM

public enum LicenseType
{
    xxx = 1,
    yyy = 2
}

2- Erstellen Sie Ihre Serviceklasse

public class LicenseTypeEnumService
    {

        public static Dictionary<int, string> GetAll()
        {

            var licenseTypes = new Dictionary<int, string>();

            licenseTypes.Add((int)LicenseType.xxx, "xxx");
            licenseTypes.Add((int)LicenseType.yyy, "yyy");

            return licenseTypes;

        }

        public static string GetById(int id)
        {

            var q = (from p in this.GetAll() where p.Key == id select p).Single();
            return q.Value;

        }

    }

3- Stellen Sie den ViewBag in Ihrem Controller ein

var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");

4- Binden Sie Ihre DropDownList

@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)
0
Mohammad Karimi