Как создать выпадающий список из перечисления enum в ASP.NET MVC?
Решение: создание универсального хелпера для enum
Отличный вопрос! В ASP.NET MVC действительно нет встроенного способа напрямую преобразовать enum в выпадающий список, но это легко решается с помощью пары вспомогательных методов. Вот самый чистый и переиспользуемый подход, который я использую в своих проектах.
Шаг 1: Создаем хелпер-расширение для Enum
Сначала напишем статический класс с методами расширения, которые будут преобразовывать любой enum в список SelectListItem:
public static class EnumHelper
{
/// <summary>
/// Преобразует enum в список SelectListItem для DropDownList
/// </summary>
public static List<SelectListItem> ToSelectList<TEnum>(this TEnum enumObj)
where TEnum : struct, Enum
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Select(value => new SelectListItem
{
Text = GetDisplayName(value),
Value = Convert.ToInt32(value).ToString()
})
.ToList();
}
/// <summary>
/// Получает отображаемое имя из атрибута Display или ToString()
/// </summary>
private static string GetDisplayName<TEnum>(TEnum value) where TEnum : struct, Enum
{
var fieldInfo = value.GetType().GetField(value.ToString());
var displayAttribute = fieldInfo?.GetCustomAttribute<DisplayAttribute>();
if (displayAttribute != null)
return displayAttribute.GetName();
return value.ToString();
}
}
Шаг 2: Добавляем атрибуты Display к enum
Теперь украсим наш enum атрибутами [Display] для читаемых имен:
using System.ComponentModel.DataAnnotations;
public enum OrderStatus
{
[Display(Name = "Новый")]
New = 0,
[Display(Name = "В обработке")]
Processing = 1,
[Display(Name = "Отгружен")]
Shipped = 2,
[Display(Name = "Доставлен")]
Delivered = 3,
[Display(Name = "Отменён")]
Cancelled = 4
}
Шаг 3: Используем в контроллере
В методе действия контроллера передаём список во ViewBag или ViewModel:
public ActionResult Edit(int id)
{
var viewModel = new OrderViewModel
{
OrderId = id,
SelectedStatus = OrderStatus.New,
// Заполняем список статусов для выпадающего списка
StatusList = new OrderStatus().ToSelectList()
};
return View(viewModel);
}
Добавьте в ViewModel свойство для списка:
public class OrderViewModel
{
public int OrderId { get; set; }
public OrderStatus SelectedStatus { get; set; }
public List<SelectListItem> StatusList { get; set; }
}
Шаг 4: В представлении Razor
И наконец, используем стандартный хелпер:
@model YourNamespace.OrderViewModel
@Html.DropDownListFor(
m => m.SelectedStatus,
Model.StatusList,
"-- Выберите статус --",
new { @class = "form-control" }
)
Преимущества этого подхода:
- Переиспользуемость: метод
ToSelectList()работает с любым enum в вашем проекте - Локализация: легко добавить поддержку ресурсов через атрибут Display
- Типобезопасность: компилятор проверяет, что вы передаёте именно enum
- Чистота кода: вся логика преобразования вынесена в отдельный класс
Если вам нужно, чтобы значение было строкой (например, "New") вместо числа, просто измените строку Value = Convert.ToInt32(value).ToString() на Value = value.ToString(). Но обычно числовые значения предпочтительнее для привязки данных.
Альтернативный подход: использование ViewBag и ручного создания списка
Если вы не хотите создавать отдельный хелпер или ваш проект небольшой, можно сделать проще — напрямую в контроллере сформировать список SelectListItem:
public ActionResult Create()
{
var statusList = Enum.GetValues(typeof(OrderStatus))
.Cast<OrderStatus>()
.Select(s => new SelectListItem
{
Text = s.ToString(), // Или используйте switch для читаемых имен
Value = ((int)s).ToString()
})
.ToList();
ViewBag.StatusList = statusList;
return View();
}
А в представлении:
@Html.DropDownList("SelectedStatus", ViewBag.StatusList as List<SelectListItem>, "Выберите статус", new { @class = "form-control" })
Недостатки:
- Код дублируется в каждом контроллере
- Нет локализации — отображаются технические имена (New, Processing и т.д.)
- ViewBag не типизирован — возможны ошибки во время выполнения
Этот метод подходит для быстрых прототипов или когда enum используется только в одном месте, но для серьёзных проектов рекомендую первый вариант с хелпером.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги