2010-09-14 14 views
8

Ho un enum per una delle proprietà del mio modello di visualizzazione. Voglio visualizzare un elenco a discesa che contiene tutti i valori dell'enumerazione. Posso farlo funzionare con il seguente codice.Come si popola un elenco a discesa con valori enum?

Quello che mi chiedo è se esiste un modo semplice per convertire da un enum a un oggetto IEnumerable? Posso farlo manualmente come nel seguente esempio, ma quando aggiungo un nuovo valore enum il codice si rompe. Immagino di poterlo fare tramite la riflessione come da questo example, ma ci sono altri modi per farlo?

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

risposta

18

sto usando un aiutante che ho trovato here per popolare le mie SelectLists con un tipo enum generica, ho fatto una piccola modifica per aggiungere la valore selezionato, però, ecco come sembra:

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

la cosa bella è che si legge la DisplayAttribute come il titolo piuttosto che il nome enum. (Se il vostro enumerazioni contengono spazi o avete bisogno di localizzazione allora rende la vita molto più facile)

quindi sarà necessario aggiungere l'attirubete di visualizzazione al enumerazioni in questo modo:

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 
} 

e questo è come si usa loro nelle tue opinioni.

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

Model.statusType è solo un oggetto enum di tipo User_Status.

Questo è tutto, basta selezionare Elenchi in ViewModels. Nel mio esempio sto rifacendo un enum nel mio ViewModel ma puoi comunque rifrare il tipo di enum direttamente nella tua vista. Lo sto facendo solo per rendere tutto pulito e bello.

Spero che sia stato utile.

+0

Ottima soluzione! –

+3

Ottima soluzione in effetti. Tuttavia, se la voce in enum non ha attributo description, fallisce. Quindi sostituisci '.First()' con '.FirstOrDefault()' e invece di 'items.Add (value, attrs.GetName());' have 'items.Add (value, attrs! = Null? Attrs.GetName (): value.ToString()); 'Questo ti fa risparmiare la digitazione in Description per ovvi voci Enum. – trailmax

+0

fatto, grazie per le correzioni. –

2

Guarda Enum.GetNames (typeof (valute))

1

Tante buone risposte - ho pensato I'sd aggiungere la mia soluzione - sto costruendo il SelectList nella vista (e non nel Controller):

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

In la mia 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

sono molto in ritardo su questo, ma ho appena trovato un wa davvero cool y per fare ciò con una riga di codice, se si è felici di aggiungere il pacchetto NuGet Unconstrained Melody (una piccola e bella libreria di Jon Skeet).

Questa soluzione è meglio perché:

  1. Assicura (con vincoli di tipo generico) che il valore è davvero un valore di enumerazione (dovuto vincolata Melodia)
  2. evita boxe inutile (a causa di non vincolata Melodia
  3. Memorizza nella cache tutte le descrizioni per evitare l'uso della riflessione su ogni chiamata (a causa della melodia non vincolata)
  4. È meno codice rispetto alle altre soluzioni!

Così, qui sono i passi per ottenere questo lavoro:

  1. In Console di Package Manager, "Installazione-Package UnconstrainedMelody"
  2. aggiungere una proprietà del modello in questo 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() }); 
        } 
    } 
    

Ora che l'elenco di SelectListItem è stato esposto sul modello, è possibile utilizzare il @ Html.DropDownList o @ Html.DropDownListPer utilizzare questa proprietà come origine.

0

Forse è troppo tardi, ma penso che potrebbe essere utile per le persone con lo stesso problema. Ho trovato here che ora con MVC 5 è incluso un EnumDropDownListFor helper HTML che rende non più necessario l'utilizzo di helper personalizzati o altre soluzioni alternative.

In questo caso particolare, basta aggiungere questo:

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

e questo è tutto!

Si può anche tradurre o modificare il testo visualizzato, tramite annotazioni di dati e file di risorse:

  1. Aggiungere le seguenti annotazioni di dati al vostro enum:

    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. Creare il file di risorse corrispondente.

Problemi correlati