Wie erstellen Sie eine Dropdownliste aus einer Enumeration in ASP.NET MVC?

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

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

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

Wie gehe ich beim Erstellen eines Dropdown-Menüs mit diesen Werten mithilfe der Erweiterungsmethode Html.DropDownList ?

Oder ist es am besten, einfach eine for-Schleife zu erstellen und die HTML-Elemente manuell zu erstellen?

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

durch using MyApp.Common

Ich weiß, dass ich zu spät zur Party komme, dachte aber, dass Sie diese Variante nützlich finden könnten, da Sie hier auch beschreibende Strings anstelle von Aufzählungskonstanten im Dropdown-Menü verwenden können. Um dies zu tun, dekorieren Sie jeden Enumerationseintrag mit einem [System.ComponentModel.Description] -Attribut.

Beispielsweise:

 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 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(this HtmlHelper htmlHelper, Expression> expression) { return EnumDropDownListFor(htmlHelper, expression, null); } public static MvcHtmlString EnumDropDownListFor(this HtmlHelper htmlHelper, Expression> expression, object htmlAttributes) { ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); Type enumType = GetNonNullableModelType(metadata); IEnumerable values = Enum.GetValues(enumType).Cast(); IEnumerable 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 Ihrer Ansicht nach tun:

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

Hoffe das hilft dir!

EDIT 2014-23. Januar: Microsoft haben gerade MVC 5.1 veröffentlicht, die jetzt eine EnumDropDownListFor-function hat. Leider scheint es das Attribut [Beschreibung] nicht zu respektieren, so dass der obige Code immer noch besteht. (Siehe http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum für die Versionshinweise von Microsoft.)

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

[Update – habe dies gerade bemerkt, und der Code sieht hier wie eine erweiterte Version des Codes aus: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating- a-dropdownlist-helper-for-enums.aspx , mit ein paar Ergänzungen. Wenn ja, würde die Zuschreibung fair erscheinen ;-)]

In ASP.NET MVC 5.1 haben sie den EnumDropDownListFor() 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) :

  

Ich stieß auf das gleiche Problem, fand diese Frage und dachte, dass die von Ash bereitgestellte Lösung nicht das war, wonach ich suchte; Das Erstellen des HTML selbst bedeutet weniger Flexibilität im Vergleich zur integrierten Html.DropDownList() function.

Stellt sich heraus, C # 3 usw. macht das ziemlich einfach. Ich habe ein enum namens 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); 

Dies erstellt eine gute SelectList , die wie gewohnt in der Ansicht verwendet werden kann:

 Status:< %=Html.DropDownList("taskStatus")%> 

Der anonyme Typ und LINQ macht dies so viel eleganter IMHO. Nichts für ungut, Ash. 🙂

Hier ist eine bessere verkapselte Lösung:

http://www.spicelogic.com/Journal/ASP-NET-MVC-DropDownListFo-Html-Helper-Enum-5

Sagen Sie hier ist Ihr Modell:

Bildbeschreibung hier eingeben

Beispiel Verwendung:

Bildbeschreibung hier eingeben

Generierte Benutzeroberfläche: Bildbeschreibung hier eingeben

Und generierte HTML

Bildbeschreibung hier eingeben

Der Quellcode des Helper Extension-Quellcodes:

Bildbeschreibung hier eingeben

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

EDIT: Hier ist der Code:

 public static class EnumEditorHtmlHelper { ///  /// Creates the DropDown List (HTML Select Element) from LINQ /// Expression where the expression returns an Enum type. ///  /// The type of the model. /// The type of the property. /// The HTML helper. /// The expression. ///  public static MvcHtmlString DropDownListFor(this HtmlHelper htmlHelper, Expression> 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)); } ///  /// Creates the select list. ///  /// Type of the enum. /// The selected item. ///  private static IEnumerable 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(); } } 

Html.DropDownListFor benötigt nur ein IEnumerable, daher ist eine Alternative zu Prizes Lösung wie folgt. So können Sie einfach schreiben:

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

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

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

EDIT: Integrierte Simons Lösung auch hier, und enthalten ToDescription-Erweiterung-Methode.

 public static class EnumExtensions { public static IEnumerable 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(); } } 

Also ohne Extension-functionen, wenn Sie einfach und einfach suchen. Das ist, was ich getan habe

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

wo XXXXX.Sites.YYYY.Models.State ist eine enum

Wahrscheinlich besser, Helfer-function, aber wenn die Zeit kurz ist, wird dies die Arbeit erledigt.

Erweitern Sie die Antworten von Prize und Rune, wenn Sie möchten, dass das Wertattribut Ihrer Auswahllistenelemente dem Ganzzahlwert des Aufzählungstyps und nicht dem Zeichenfolgenwert zugeordnet wird, verwenden Sie den folgenden Code:

 public static SelectList ToSelectList(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 Enumeration-Wert als ein TEnum-Objekt zu behandeln, können wir ihn als ein Objekt behandeln und dann in einen Integer-Wert umwandeln, um den ungepackten Wert zu erhalten.

Anmerkung: Ich habe auch eine generische Typbeschränkung hinzugefügt, um die Typen einzuschränken, für die diese Erweiterung nur für Strukturen verfügbar ist (Enums Basistyp), und eine Laufzeittypvalidierung, die sicherstellt, dass die übergebene Struktur tatsächlich eine Enum ist.

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

Um das Problem zu lösen, die Nummer anstelle von Text mit der Verlängerungsmethode von Prize zu erhalten.

 public static SelectList ToSelectList(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); } 

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

Dies ermöglicht die Verwendung der Enumeration im Modell. Im Wesentlichen besteht die Idee darin, eine Integer-Eigenschaft sowie die Enumeration zu verwenden und die Integer-Eigenschaft zu emulieren.

Verwenden Sie dann das [System.ComponentModel.Description] -Attribut, um das Modell mit Ihrem Anzeigetext zu kommentieren, und verwenden Sie eine “EnumDropDownListFor” -Erweiterung in Ihrer Ansicht.

Dies macht sowohl die Ansicht als auch das Modell sehr 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 CuriousQuestion{ get; set; } public virtual Nullable CuriousQuestionId { get { return (Nullable)CuriousQuestion; } set { CuriousQuestion = (Nullable)value; } } 

Aussicht:

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

Erweiterung (direkt aus der Antwort von Simon Goldstone , hier aus Gründen der Vollständigkeit enthalten):

 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 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(this HtmlHelper htmlHelper, Expression> expression) { return EnumDropDownListFor(htmlHelper, expression, null); } public static MvcHtmlString EnumDropDownListFor(this HtmlHelper htmlHelper, Expression> expression, object htmlAttributes) { ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); Type enumType = GetNonNullableModelType(metadata); IEnumerable values = Enum.GetValues(enumType).Cast(); IEnumerable 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 möchten etwas wie Enum.GetValues

Ein super einfacher Weg, um das zu schaffen – ohne all die Erweiterungen, die übertrieben scheinen:

Deine enum:

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

Innerhalb Ihres Controllers binden Sie die Enum an eine Liste:

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

Danach casting 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 benötigt keine Erweiterungen oder irgendetwas so verrückt.

UPDATE : Siehe Andrews Kommentar unten.

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

Dies ist eine Rune & Prize-Antwort, die geändert wurde, um den Enum int Wert als ID zu verwenden.

Beispiel Enum:

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

Erweiterungsmethode:

  public static SelectList ToSelectList(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())); } 

Beispiel für die Verwendung:

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

Denken Sie daran, den Namespace mit der Erweiterungsmethode zu importieren

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

Beispiel für generiertes HTML:

  

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

Dies ist die Version für Razor:

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

Jetzt wird diese function in MVC 5.1 über @Html.EnumDropDownListFor()

Überprüfen Sie den folgenden Link:

http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum

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

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

Diese Lösung ist besser, weil:

  1. Es stellt sicher (bei generischen Typ-Constraints), dass der Wert wirklich ein Enum-Wert ist (wegen Unconstrained Melody)
  2. Es vermeidet unnötiges Boxen (wegen Unconstrained Melody)
  3. Es speichert alle Beschreibungen zwischen, um Reflektionen bei jedem Aufruf zu vermeiden (wegen Unconstrained Melody)
  4. Es ist weniger Code als die anderen Lösungen!

Also, hier sind die Schritte, damit das funktioniert:

  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 AllItems { get { return Enums.GetValues().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() }); } } 

Jetzt, da Sie die List of SelectListItem in Ihrem Modell verfügbar gemacht haben, können Sie die @ Html.DropDownList oder @ Html.DropDownListFor verwenden, um diese Eigenschaft als Quelle zu verwenden.

Aufbauend auf Simons Antwort besteht ein ähnlicher Ansatz darin, die Enum-Werte aus einer Ressourcendatei anstatt in einem Beschreibungsattribut innerhalb der Enum selbst anzuzeigen. Dies ist hilfreich, wenn Ihre Site in mehr als einer Sprache gerendert werden muss und wenn Sie eine spezifische Ressourcendatei für Enums hätten, könnten Sie einen Schritt weiter gehen und nur Enum-Werte in Ihrer Enum haben und sie von der Erweiterung aus referenzieren eine Konvention wie [EnumName] _ [EnumValue] – letztendlich weniger tippen!

Die Erweiterung sieht dann so aus:

 public static IHtmlString EnumDropDownListFor(this HtmlHelper html, Expression> expression) { var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType; var enumValues = Enum.GetValues(enumType).Cast(); 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 enumValue) { var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue); return Enums.ResourceManager.GetString(key) ?? enumValue.ToString(); } 

Ressourcen in der Enums.Resx-Datei, die wie ItemTypes_Movie aussehen: Film

Eine andere Sache, die ich tun möchte, ist, anstatt die Erweiterungsmethode direkt aufzurufen, würde ich es lieber mit einem @ Html.EditorFor (x => x.MyProperty) aufrufen, oder im Idealfall nur das ganze Formular in einem ordentlichen @ Html.EditorForModel (). Um dies zu tun, ändere ich die Zeichenkette so, dass sie 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 Sie das interessiert, habe ich hier auf meinem Blog eine viel detailliertere Antwort gegeben:

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

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

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

In Ihrem Controller:

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

In deiner Sicht:

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

Die Helferklasse:

 public static class EnumHelper { // Get the value of the description attribute if the // enum has one, otherwise use the value. public static string GetDescription(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(); } ///  /// Build a select list for an enum ///  public static SelectList SelectListFor() where T : struct { Type t = typeof(T); return !t.IsEnum ? null : new SelectList(BuildSelectListItems(t), "Value", "Text"); } ///  /// Build a select list for an enum with a particular value selected ///  public static SelectList SelectListFor(T selected) where T : struct { Type t = typeof(T); return !t.IsEnum ? null : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString()); } private static IEnumerable BuildSelectListItems(Type t) { return Enum.GetValues(t) .Cast() .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() }); } } 

Ein weiterer Fix für diese Erweiterungsmethode – die aktuelle Version hat den aktuellen Wert der Enumeration nicht ausgewählt. Ich habe die letzte Zeile repariert:

 public static SelectList ToSelectList(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()); } 

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

 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 here the typeof(Resources) is the resource you want to load, and then you get the localized String, also useful if your enumerator has values with multiple words.

This is my version of helper method. 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(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); } 

You can also use my custom HtmlHelpers in Griffin.MvcContrib. The following code:

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

Generates:

Bildbeschreibung hier eingeben

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

I found an answer here http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx ; however, some of my enums have [Description(...)] attribute, so I’ve modified the code to provide support for that:

  enum Abc { [Description("Cba")] Abc, Def } public static MvcHtmlString EnumDropDownList(this HtmlHelper htmlHelper, string name, TEnum selectedValue) { IEnumerable values = Enum.GetValues(typeof(TEnum)) .Cast(); List items = new List(); 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.

@Simon Goldstone: Thanks for your solution, it can be perfectly applied in my case. The only problem is I had to translate it to VB. But now it is done and to save other people’s time (in case they need it) I put it here:

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

End You use it like this:

 @Html.EnumDropDownListFor(Function(model) (model.EnumField)) 

I ended up creating extention methods to do what is essentially the accept answer here. The last half of the Gist deals with Enum specifically.

https://gist.github.com/3813767

 @Html.DropdownListFor(model=model->Gender,new List { new ListItem{Text="Male",Value="Male"}, new ListItem{Text="Female",Value="Female"}, new ListItem{Text="--- Select -----",Value="-----Select ----"} } ) 
 @Html.DropDownListFor(model => model.MaritalStatus, new List { new SelectListItem { Text = "----Select----", Value = "-1" }, new SelectListItem { Text = "Marrid", Value = "M" }, new SelectListItem { Text = "Single", Value = "S" } }) 

Here a Martin Faartoft variation where you can put custom labels which is nice for localization.

 public static class EnumHtmlHelper { public static SelectList ToSelectList(this TEnum enumObj, Dictionary 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); } } 

Use in view:

 @Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary() { { 1, ContactResStrings.FeedbackCategory }, { 2, ContactResStrings.ComplainCategory }, { 3, ContactResStrings.CommentCategory }, { 4, ContactResStrings.OtherCategory } }), new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.Category) 

I’ve done the following and works successfully:

  • In the view.cshtml:

@model MyModel.cs

 @Html.EnumDropDownListFor(m=>m.MyItemType ) 
  • In the Model: MyModel.cs

public ItemTypes MyItemType { get; set; }