ASP.NET MVC: Отображаем Enum в Html.DropDownListFor
Сайтостроение | создано: 10.07.2012 | опубликовано: 10.07.2012 | обновлено: 13.01.2024 | просмотров: 13668
Наверное трудно себе представить более или менее серьёзный проект без использования 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"}
};
Покажите представление
Представление по умолчанию отобразит что-то типа этого:

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

Заметно, наверное, что не очень похоже на выпадающий список. Попробуем теперь применить хелпер из 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. Это расширение из библиотеке. Теперь уже гораздо лучше:

Локализация Enum (способ 1)
А теперь научим этот EnumDropDownList “говорить” по-русски. Для этого достаточно просто отметить каждое из значений перечисления атрибутом DisplayAttribute из сборки DataAnnotation.
public enum Country {
[Display(Name="Российская федерация")]
Russia,
[Display(Name="Америка")]
USA,
[Display(Name = "Канада")]
Canada
}

Ну, вот! Уже совсем другое дело! Дальше – больше!
Локализация Enum (способ 2)
А если хочется большего? Например, использовать ресурсные файлы? Легко! Для начала сразу применим атрибут DisplayAttribute, только теперь немного по-другому:
public enum Country {
[Display(ResourceType=typeof(Resources))]
Russia,
[Display(ResourceType = typeof(Resources))]
USA,
[Display(ResourceType = typeof(Resources))]
Canada
}
Раз используем ресурный файл – надо бы его создать.

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

Работает!!! Только надо бы сделать одно важное примечание: ресурсный файл имеет больший приоритет перед первым способом. То есть, если задан ресурс, [Display(Name=”…”)] игнорируется.
В качестве заключения
К сожалению, пока нет времени сделать поддержку глобализации в ресурсных файлах (типа Resources.en-US.resx или resources.fr-FR.resx), но такая работа запланирована.