ASP.NET MVC: Отображаем Enum в Html.DropDownListFor

ru-RU | создано: 10.07.2012 | опубликовано: 10.07.2012 | обновлено: 01.01.2018 | просмотров за всё время: 11089

Наверное трудно себе представить более или менее серьёзный проект без использования Enum. Я покажу как можно отобразить на представлении (View) любой Enum с локализацией через Resource-файл и/или через DisplayAttribute.

В качестве вступления

Наверное вам не раз приходилось использовать Enum в своих проектах на ASP.NET MVC. И могу предположить, что при редактировании и добавления новой сущности, у которой свойство являло собой перечисление (Enum), вам приходилось выдумывать разные "приспособления". Скажу честно, мне тоже пришлось “покувыраться” с перечислениями (Enum). После непродолжительных танцев с бубнами, я в очередной раз расширил функционал nuget-пакета MvcTools, добавив в сборку Html.EnumDropDownListFor. Об этом расширении и пойдет речь.

Модель на сцену!

Допустим, у меня есть модель, которую надо редактировать. Одно из свойств класса Country типа Enum.

public class Person {
    /// <summary>
    /// Идентификатор
    /// </summary>
    [Display(Name = "Идентификатор")]
    [Required(ErrorMessage = "Идентификатор - обязательно поле")]
    public int Id { get; set; }

    /// <summary>
    /// Наименование
    /// </summary>
    [Display(Name = "Наименование")]
    [Required(ErrorMessage = "Наименование - обязательно поле")]
    [StringLength(50, ErrorMessage = "Наименование не может длиннее 50 символов")]
    public String Name { get; set; }

    /// <summary>
    /// Наименование для меню
    /// </summary>
    [Display(Name = "Наименование для меню")]
    [Required(ErrorMessage = "Наименование для меню - обязательно поле")]
    [StringLength(50, ErrorMessage = "Наименование для меню не может длиннее 50 символов")]
    public String DisplayName { get; set; }

    /// <summary>
    /// Страна
    /// </summary>
    [Display(Name = "Страна")]
    [Required(ErrorMessage = "Страна - обязательно поле")]
    public Country Country { get; set; }

    /// <summary>
    /// Дата регистрации
    /// </summary>
    [Display(Name = "Дата регистрации")]
    [Required(ErrorMessage = "Дата регистрации - обязательно поле")]
    [DataType(DataType.Date)]
    public DateTime CreatedAt { get; set; }
}

Само перечисление имеет вид:

public enum Country {
   Russia,
   USA,
   Canada
}

В метод контролера добавлю некоторые данные для примера:

List<Person> _list = new List<Person>() { 
    new Person { Country = Country.Russia,
        CreatedAt = new DateTime(2012,1,5),
        DisplayName = "Василий",
        Id =1042,
        Name = "Vasiliy"},
        new Person { Country = Country.Canada,
        CreatedAt = new DateTime(2012,1,15),
        DisplayName = "Иван",
        Id =122,
        Name = "Ivan"},
        new Person { Country = Country.USA,
        CreatedAt = new DateTime(2012,2,3),
        DisplayName = "Коля",
        Id =12,
        Name = "Nic"}            
};

Покажите представление

Представление по умолчанию отобразит что-то типа этого:

88-0

 

Если открыть страницу редактирования, например, первого “Василия”, то я увижу следующее:

88-1

 

Заметно, наверное, что не очень похоже на выпадающий список. Попробуем теперь применить хелпер из nuget-пакета MvcTools:

 <div class="editor-label">
     @Html.LabelFor(model => model.Country)
 </div>
 <div class="editor-field">
     @Html.EnumDropDownListFor(model => model.Country)
     @Html.ValidationMessageFor(model => model.CreatedAt)
 </div>

Обратите внимание на строку номер 5. Это расширение из библиотеке. Теперь уже гораздо лучше:

88-2

Локализация Enum (способ 1)

А теперь научим этот EnumDropDownList “говорить” по-русски. Для этого достаточно просто отметить каждое из значений перечисления атрибутом DisplayAttribute из сборки DataAnnotation.

public enum Country {
   [Display(Name="Российская федерация")]
   Russia,
   [Display(Name="Америка")]
   USA,
   [Display(Name = "Канада")]
   Canada
}

88-3

Ну, вот! Уже совсем другое дело! Дальше – больше!

Локализация Enum (способ 2)

А если хочется большего? Например, использовать ресурсные файлы? Легко! Для начала сразу применим атрибут DisplayAttribute, только теперь немного по-другому:

public enum Country {
   [Display(ResourceType=typeof(Resources))]
   Russia,
   [Display(ResourceType = typeof(Resources))]
   USA,
   [Display(ResourceType = typeof(Resources))]
   Canada
}

Раз используем ресурный файл – надо бы его создать.

88-4

Ключевые моменты помечены на картинке. Запускаем!

 

88-5

Работает!!! Только надо бы сделать одно важное примечание: ресурсный файл имеет больший приоритет перед первым способом. То есть, если задан ресурс, [Display(Name=”…”)] игнорируется.

В качестве заключения

К сожалению, пока нет времени сделать поддержку глобализации в ресурсных файлах (типа Resources.en-US.resx или resources.fr-FR.resx), но такая работа запланирована.