Как заполнить выпадающий список значениями перечисления? - PullRequest
8 голосов
/ 14 сентября 2010

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

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

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

Ответы [ 5 ]

18 голосов
/ 14 сентября 2010

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

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 - это просто объект enum типа User_Status.

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

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

2 голосов
/ 04 февраля 2013

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

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

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

Итак, вот шаги, чтобы заставить это работать:

  1. В консоли диспетчера пакетов "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 для использованияэто свойство как источник.

2 голосов
/ 14 сентября 2010

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

1 голос
/ 22 июля 2015

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

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

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

1 голос
/ 07 марта 2012

Так много хороших ответов - я думал, что добавлю свое решение - я строю список выбора в представлении (а не в контроллере):

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

HTH

...