2010-09-14 7 views
8

У меня есть перечисление для одного из свойств моей модели представления. Я хочу отобразить раскрывающийся список, содержащий все значения перечисления. Я могу заставить это работать со следующим кодом.Как заполнить выпадающий список значениями перечисления?

Что мне интересно, есть ли простой способ конвертировать из enum в IEnumerable? Я могу сделать это вручную, как в следующем примере, но когда я добавляю новое значение перечисления, код прерывается. Я полагаю, что я могу сделать это через отражение в соответствии с этим example, но но есть ли другие способы сделать это?

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

ответ

18

Я использую помощник, который я нашел here заполнить мои SelectLists с общим перечислимого типа, я сделал небольшое изменение, чтобы добавить выбранное значение, хотя, вот как это выглядит:

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

хорошая вещь об этом является то, что он читает DisplayAttribute как заголовок, а не имя перечислений. (Если ваши перечисления содержат пробела или вам нужны локализация, то это делает вашу жизнь намного проще)

Так что вам нужно будет добавить дисплей attirubete своих перечислениям, как это:

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 
} 

и это, как вы используете их в ваших взглядах.

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

Model.statusType это просто перечисление объект типа User_Status.

Вот и все, больше не выбирайте списки в своих моделях ViewModels. В моем примере я переопределяю enum в моей ViewModel, но вы можете Refrence тип перечисления прямо в вашем представлении. Я просто делаю это, чтобы сделать все чистое и приятное.

Надеюсь, что это было полезно.

+0

Отличное решение! –

+3

Отличное решение. Однако, если запись в enum не имеет атрибута описания, она терпит неудачу. Поэтому замените '.First()' на '.FirstOrDefault()' и вместо 'items.Add (value, attrs.GetName());' have 'items.Add (значение, attrs! = Null? Attrs.GetName (): value.ToString()); 'Это экономит ваш ввод в описании для очевидных записей Enum. – trailmax

+0

сделано, спасибо за исправления. –

2

Посмотрите на Enum.GetNames (TYPEOF (валюты))

1

Так много хороших ответов, - подумал я I'sd добавить мое решение - я строить SelectList в представлении (а не в контроллере):

В моей 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; } 
} 

В мой 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       
    }) 

НТН

1

Я очень поздно на этом, но я только что нашел действительно прохладный ва y сделать это с помощью одной строки кода, если вы с удовольствием добавите пакет NuGet Unconstrained Melody (хорошая небольшая библиотека от Jon Skeet).

Это решение лучше, потому что:

  1. Это обеспечивает (с ограничениями универсального типа), что значение действительно является значением перечисления (из-за Безусловную Melody)
  2. Это позволяет избежать ненужного бокса (из-за Безусловную Melody)
  3. Он кэширует все описания, чтобы избежать отражения при каждом вызове (из-за Unconstrained Melody)
  4. Это меньше кода, чем другие решения!

Итак, вот шаги, чтобы получить эту работу:

  1. В Package Manager Console, "Install-Package UnconstrainedMelody"
  2. Добавить свойство на вашей модели, как так:

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

Теперь, когда у вас есть список SelectListItem, выставленный на вашей модели, вы можете использовать @ Html.DropDownList или @ Html.DropDownListДля использования этого свойства в качестве источника.

0

Возможно, слишком поздно, но я думаю, что это может быть полезно для людей с одинаковой проблемой. Я нашел here, что теперь с MVC 5 включен EnumDropDownListFor html helper, который больше не требует использования пользовательских помощников или других обходных решений.

В данном конкретном случае, просто добавьте это:

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

и это все!

Вы также можете перевести или изменить отображаемый текст с помощью аннотаций данных и файлов ресурсов:

  1. Добавьте следующие аннотации данных для вашего перечисления:

    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. Создать соответствующий файл ресурсов.

Смежные вопросы