2010-09-14 32 views
8

Tengo una enumeración para una de las propiedades de mi modelo de vista. Quiero mostrar una lista desplegable que contiene todos los valores de la enumeración. Puedo hacer que esto funcione con el siguiente código.¿Cómo lleno una lista desplegable con valores enum?

Lo que me pregunto es si hay una manera simple de convertir de una enumeración a un Enumerable? Puedo hacerlo manualmente como en el siguiente ejemplo, pero cuando agrego un nuevo valor enum, el código se rompe. Me imagino que puedo hacerlo a través de la reflexión según esta example, pero ¿hay otras formas de hacerlo?

public enum Currencies 
{ 
    CAD, USD, EUR 
} 

public ViewModel 
{ 
    [Required] 
    public Currencies SelectedCurrency {get; set;} 

    public SelectList Currencies 
    { 
    List<Currencies> c = new List<Currencies>(); 
    c.Add(Currencies.CAD); 
    c.Add(Currencies.USD); 
    c.Add(Currencies.EUR); 

    return new SelectList(c); 
    } 
} 

Respuesta

18

que estoy usando un ayudante que encontré here para poblar mis SelectLists con un tipo de enumeración genérica, lo hice una pequeña modificación para añadir el valor seleccionado, sin embargo, así es como se ve:

public static SelectList ToSelectList<T>(this T enumeration, string selected) 
{ 
    var source = Enum.GetValues(typeof(T)); 

    var items = new Dictionary<object, string>(); 

    var displayAttributeType = typeof(DisplayAttribute); 

    foreach (var value in source) 
    { 
     FieldInfo field = value.GetType().GetField(value.ToString()); 

     DisplayAttribute attrs = (DisplayAttribute)field. 
         GetCustomAttributes(displayAttributeType, false).FirstOrDefault() 

     items.Add(value, attrs != null ? attrs.GetName() : value.ToString()); 
    } 

    return new SelectList(items, "Key", "Value", selected); 
} 

el bueno de esto es que se lee el DisplayAttribute como el título en lugar del nombre de enumeración. (Si sus enumeraciones contienen espacios o que necesitan la localización entonces se le hace la vida mucho más fácil)

por lo que tendrá que añadir el attirubete Pantalla a sus enumeraciones de esta manera:

public enum User_Status 
{ 
    [Display(Name = "Waiting Activation")] 
    Pending, // User Account Is Pending. Can Login/Can't participate 

    [Display(Name = "Activated")] 
    Active,    // User Account Is Active. Can Logon 

    [Display(Name = "Disabled")] 
    Disabled,   // User Account Is Diabled. Can't Login 
} 

y así es como se utiliza ellos en tus puntos de vista.

<%: Html.DropDownList("ChangeStatus" , ListExtensions.ToSelectList(Model.statusType, user.Status))%> 

Model.statusType es sólo un objeto enum de tipo User_Status.

Eso es todo, no más listas de selección en su ViewModels. En mi ejemplo, estoy refrencing una enumeración en mi ViewModel, pero puede Refrence el tipo de enumeración directamente en su vista sin embargo. Solo lo hago para que todo esté limpio y agradable.

Espero que haya sido útil.

+0

¡Gran solución! –

+3

Gran solución de hecho. Sin embargo, si la entrada en enum no tiene atributo de descripción, falla. Reemplace '.First()' con '.FirstOrDefault()' y en lugar de 'items.Add (value, attrs.GetName());' tenga 'items.Add (value, attrs! = Null? Attrs.GetName (): value.ToString()); 'Eso te ahorra escribir en Descripción para las entradas obvias de Enum. – trailmax

+0

hecho, gracias por las correcciones. –

2

Mira Enum.GetNames (typeof (Monedas))

1

Tantas buenas respuestas - pensé I'sd añadir mi solución - Estoy construyendo el SelectList en la vista (y no en el PLC):

En mi C#:

namespace ControlChart.Models 
//My Enum 
public enum FilterType { 
[Display(Name = "Reportable")]  
Reportable = 0,  
[Display(Name = "Non-Reportable")]  
NonReportable,  
[Display(Name = "All")]  
All }; 

//My model: 
public class ChartModel { 
[DisplayName("Filter")] 
public FilterType Filter { get; set; } 
} 

En mi cshtml:

@using System.ComponentModel.DataAnnotations 
@using ControlChart.Models 
@model ChartMode 
@*..........*@ 
@Html.DropDownListFor(x => x.Filter,       
from v in (ControlChart.Models.FilterType[])(Enum.GetValues(typeof(ControlChart.Models.FilterType))) 
select new SelectListItem() { 
    Text = ((DisplayAttribute)(typeof(FilterType).GetField(v.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false).First())).Name,        
    Value = v.ToString(),        
    Selected = v == Model.Filter       
    }) 

HTH

1

estoy muy a última hora del este, pero acabo de encontrar un wa muy cool y hacer esto con una línea de código, si está contento de agregar el paquete NuGet Unconstrained Melody (una pequeña y bonita biblioteca de Jon Skeet).

Esta solución es mejor porque:

  1. Se asegura (con limitaciones de tipo genérico) que el valor de verdad es un valor de enumeración (debido a Unconstrained Melody)
  2. Evita el boxeo innecesaria (debido a Unconstrained Melody)
  3. Guarda 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!

lo tanto, aquí están los pasos para conseguir este trabajo:

  1. En la consola de Administrador de paquetes, "Instalar Paquete UnconstrainedMelody"
  2. añadir un alojamiento del modelo de este modo:

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

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

0

Quizás sea demasiado tarde, pero creo que podría ser útil para personas con el mismo problema. He encontrado here que ahora con MVC 5 está incluido un EnumDropDownListFor html helper que hace que ya no sea necesario el uso de ayuda personalizada u otras soluciones.

En este caso particular, sólo tiene que añadir esto:

@Html.EnumDropDownListFor(x => x.SelectedCurrency) 

y eso es todo!

También se puede traducir o cambiar el texto que se muestra a través de anotaciones de datos y archivos de recursos:

  1. Añadir las siguientes anotaciones de datos a su enumeración:

    public enum Currencies 
    { 
        [Display(Name="Currencies_CAD", ResourceType=typeof(Resources.Enums)] 
        CAD, 
        [Display(Name="Currencies_USD", ResourceType=typeof(Resources.Enums)]  
        USD, 
        [Display(Name="Currencies_EUR", ResourceType=typeof(Resources.Enums)] 
        EUR 
    } 
    
  2. Crear el archivo de recursos correspondiente.

Cuestiones relacionadas