¿Cómo se crea una lista desplegable a partir de una enumeración en ASP.NET MVC?

Html.DropDownList utilizar el método de extensión Html.DropDownList pero no puedo encontrar la forma de usarlo con una enumeración.

Digamos que tengo una enumeración como esta:

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

¿Cómo hago para crear un menú desplegable con estos valores usando el método de extensión Html.DropDownList ?

¿O es mi mejor opción simplemente crear un bucle for y crear los elementos Html manualmente?

Para MVC v5.1 use Html.EnumDropDownListFor

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

Para MVC v5 usa EnumHelper

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

Para MVC 5 y menor

Puse la respuesta de Rune en un método de extensión:

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

Esto te permite escribir:

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

mediante el using MyApp.Common

Sé que llego tarde a la fiesta, pero pensé que esta variante podría resultarle útil, ya que esta también le permite usar cadenas descriptivas en lugar de constantes de enumeración en el menú desplegable. Para ello, decore cada entrada de enumeración con un atributo [System.ComponentModel.Description].

Por ejemplo:

 public enum TestEnum { [Description("Full test")] FullTest, [Description("Incomplete or partial test")] PartialTest, [Description("No test performed")] None } 

Aquí está mi código:

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

A continuación, puede hacer esto en su vista:

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

¡Espero que esto te ayude!

EDIT 2014-ENE-23: Microsoft acaba de lanzar MVC 5.1, que ahora tiene una función EnumDropDownListFor. Lamentablemente, no parece respetar el atributo [Descripción] por lo que el código anterior sigue en pie. (Consulte http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum para ver las notas de la versión de Microsoft).

Actualización: Sin embargo, admite el atributo Mostrar [Display(Name = "Sample")] , así que uno puede usar eso.

[Actualización: solo noté esto, y el código parece una versión extendida del código aquí: http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating- a-dropdownlist-helper-for-enums.aspx , con un par de adiciones. Si es así, la atribución parecería justa ;-)]

En ASP.NET MVC 5.1 , agregaron el EnumDropDownListFor() , por lo que no es necesario extensiones personalizadas:

Modelo :

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

Vista :

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

Usando Tag Helper (ASP.NET MVC 6) :

  

Me encontré con el mismo problema, encontré esta pregunta, y pensé que la solución provista por Ash no era lo que estaba buscando; Tener que crear el HTML por mí mismo significa menos flexibilidad en comparación con la función incorporada Html.DropDownList() .

Resulta C # 3 etc. hace esto bastante fácil. Tengo una enum llamada 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); 

Esto crea una buena lista de SelectList que se puede usar como lo que está acostumbrado en la vista:

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

El tipo anónimo y LINQ lo hace mucho más elegante en mi humilde opinión. Sin ofender, Ash. 🙂

Aquí hay una mejor solución encapsulada:

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

Diga, aquí está su modelo:

enter image description here

Uso de la muestra:

enter image description here

UI generada: enter image description here

Y HTML generado

enter image description here

La foto instantánea del código fuente de la extensión de ayudante:

enter image description here

Puede descargar el proyecto de muestra desde el enlace que proporcioné.

EDITAR: Aquí está el código:

 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 solo requiere un IEnumerable, por lo que una alternativa a la solución de Prize es la siguiente. Esto te permitirá simplemente escribir:

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

[Donde SelectedItemType es un campo en su modelo de tipo ItemTypes, y su modelo no es nulo]

Además, no es necesario genizar el método de extensión, ya que puede usar enumValue.GetType () en lugar de typeof (T).

EDITAR: Aquí también se incluye la solución integrada de Simon e incluye el método de extensión ToDescription.

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

Así que sin las funciones de extensión si buscas simple y fácil … Esto es lo que hice

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

donde XXXXX.Sites.YYYY.Models.State es una enumeración

Probablemente sea mejor hacer la función auxiliar, pero cuando el tiempo es corto esto hará el trabajo.

Ampliando las respuestas de Prune y Rune, si desea que el atributo value de sus elementos de la lista de selección se asocie al valor entero del tipo Enumeration, en lugar del valor de la cadena, use el siguiente código:

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

En lugar de tratar cada valor de enumeración como un objeto TEnum, podemos tratarlo como un objeto y luego convertirlo en un número entero para obtener el valor no incluido.

Nota: También agregué una restricción de tipo genérico para restringir los tipos para los cuales esta extensión está disponible solo para estructuras (tipo de base de Enum) y una validación de tipo de tiempo de ejecución que asegura que la estructura pasada es de hecho Enum.

Actualización 10/23/12: Se agregó un parámetro de tipo genérico para el tipo subyacente y un problema fijo de no comstackción que afecta a .NET 4+.

Para resolver el problema de obtener el número en lugar de texto utilizando el método de extensión del Premio.

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

La mejor solución que encontré para esto fue la combinación de este blog con la respuesta de Simon Goldstone .

Esto permite el uso de la enumeración en el modelo. Básicamente, la idea es usar una propiedad entera así como la enumeración, y emular la propiedad entera.

A continuación, utilice el atributo [System.ComponentModel.Description] para anotar el modelo con su texto de visualización, y use una extensión “EnumDropDownListFor” en su vista.

Esto hace que tanto la vista como el modelo sean muy legibles y mantenibles.

Modelo:

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

Ver:

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

Extensión (directamente de la respuesta de Simon Goldstone , incluida aquí para completar):

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

Desea ver el uso de algo así como Enum.GetValues

Una manera súper fácil de hacer esto, sin todas las extensiones que parecen excesivas, es esta:

Tu enum:

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

Dentro de tu controlador, une el Enum a una lista:

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

Después de eso, tíralo a ViewBag:

  ViewBag.RequiredLevel = new SelectList(myLevels); 

Finalmente, simplemente conéctelo a la Vista:

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

Esta es, de lejos, la forma más fácil que encontré y no requiere ninguna extensión o algo tan loco.

ACTUALIZACIÓN : vea el comentario de Andrews a continuación.

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

Estas son las respuestas de Rune & Prize alteradas para usar el valor int Enum como ID.

Muestra Enum:

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

Método de extensión:

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

Muestra de uso:

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

Recuerde Importar el espacio de nombres que contiene el método de Extensión

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

Muestra de HTML generado:

  

Tenga en cuenta que el elemento que usa para llamar a la ToSelectList de selección es el elemento seleccionado.

Esta es la versión para 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) 

Ahora esta característica se admite de @Html.EnumDropDownListFor() en MVC 5.1 a través de @Html.EnumDropDownListFor()

Mira el siguiente enlace:

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

¡Es realmente una vergüenza que Microsoft haya tardado 5 años en implementar tal característica, que es tan solicitada de acuerdo con la votación anterior!

Estoy muy avanzado en esto, pero acabo de encontrar una manera genial de hacer esto con una línea de código, si está contento de agregar el paquete NuGet sin restricciones (una buena y pequeña biblioteca de Jon Skeet).

Esta solución es mejor porque:

  1. Asegura (con restricciones de tipo genérico) que el valor es realmente un valor enum (debido a la Melodía no restringida)
  2. Evita el boxeo innecesario (debido a la melodía no restringida)
  3. Almacena en caché todas las descripciones para evitar el uso de la reflexión en cada llamada (debido a Melodía no restringida)
  4. ¡Es menos código que las otras soluciones!

Entonces, aquí están los pasos para hacer que esto funcione:

  1. En la consola de Package Manager, “Install-Package UnconstrainedMelody”
  2. Agregue una propiedad en su modelo así:

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

Ahora que tiene la Lista de SelectListItem expuesta en su modelo, puede usar @ Html.DropDownList o @ Html.DropDownListFor usando esta propiedad como fuente.

Basándose en la respuesta de Simon, un enfoque similar es hacer que los valores de Enum se muestren desde un archivo de recursos, en lugar de mostrarlos en un atributo de descripción dentro de Enum. Esto es útil si su sitio debe representarse en más de un idioma y si tuviera un archivo de recursos específico para Enums, podría ir un paso más allá y tener solo valores Enum, en su Enum y hacer referencia a ellos desde la extensión por una convención como [EnumName] _ [EnumValue] – ¡en última instancia, menos tipeo!

La extensión se ve así:

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

Recursos en el archivo Enums.Resx mirando como ItemTypes_Movie: Film

Otra cosa que me gustaría hacer es, en lugar de llamar directamente al método de extensión, prefiero llamarlo con @ Html.EditorFor (x => x.MyProperty), o lo ideal es tener todo el formulario, en un solo nombre @ Html.EditorForModel () Para hacer esto, cambio la plantilla de cadena para que se vea así

 @using MVCProject.Extensions @{ var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType; @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x)) } 

Si esto te interesa, he puesto una respuesta mucho más detallada aquí en mi blog:

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

Bueno, llegué muy tarde a la fiesta, pero por lo que vale, EnumHelper un blog sobre este mismo tema mediante el cual creo una clase EnumHelper que permite una transformación muy fácil.

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

En tu controlador:

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

En su vista:

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

La clase de ayudante:

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

Otra solución para este método de extensión: la versión actual no seleccionaba el valor actual de la enumeración. Arreglé la última línea:

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

If you want to add localization support just change the s.toString() method to something like this:

 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. Yo uso esto:

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

En lugar de eso:

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

Aquí está:

 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)

Genera:

enter image description here

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

Espero que ayude.

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