Как создать раскрывающийся список из перечисления в ASP.NET MVC?

Я пытаюсь использовать метод расширения Html.DropDownList, но не могу понять, как использовать его с перечислением.

Скажем, у меня есть такое перечисление:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

Как мне создать раскрывающийся список с этими значениями с помощью метода расширения Html.DropDownList?

Или лучше всего просто создать цикл for и вручную создавать элементы Html?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
697
0
384 628
36
Перейти к ответу Данный вопрос помечен как решенный

Ответы 36

Вы хотите использовать что-то вроде Enum.GetValues

ОБНОВЛЕНО - Я бы посоветовал использовать предложение Rune ниже, а не эту опцию!


Я предполагаю, что вы хотите выплюнуть что-то вроде следующего:

<select name = "blah">
    <option value = "1">Movie</option>
    <option value = "2">Game</option>
    <option value = "3">Book</option>
</select>

что вы можете сделать с помощью метода расширения примерно следующего вида:

public static string DropdownEnum(this System.Web.Mvc.HtmlHelper helper,
                                  Enum values)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append("<select name=\"blah\">");
    string[] names = Enum.GetNames(values.GetType());
    foreach(string name in names)
    {
        sb.Append("<option value=\"");
        sb.Append(((int)Enum.Parse(values.GetType(), name)).ToString());
        sb.Append("\">");
        sb.Append(name);
        sb.Append("</option>");
    }
    sb.Append("</select>");
    return sb.ToString();
}

НО подобные вещи нельзя локализовать (т.е. их будет сложно перевести на другой язык).

Примечание: вам нужно вызвать статический метод с экземпляром Enumeration, то есть Html.DropdownEnum(ItemTypes.Movie);

Может быть более элегантный способ сделать это, но все вышеперечисленное работает.

Спасибо. На самом деле это реализация, к которой я пришел, но я надеялся, что она уже встроена в структуру. Думаю, нет. :-(

Kevin Pang 24.12.2008 01:05

Если я правильно помню, для этого было что-то в MvcContrib.

Arnis Lapsa 12.10.2009 13:07

Я согласен с вашим обновлением - решения, опубликованные Rune & Prize, намного аккуратнее, оставляя фактическую разметку для отображения в представлении.

belugabob 12.10.2009 14:21

Я столкнулся с той же проблемой, нашел этот вопрос и подумал, что решение, предоставленное Эшем, не то, что я искал; Самостоятельное создание HTML означает меньшую гибкость по сравнению со встроенной функцией Html.DropDownList().

Оказывается, C# 3 и т. д. Делают это довольно просто. У меня есть enum под названием TaskStatus:

var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
               select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);

Это создает старый добрый SelectList, который можно использовать, как вы привыкли, в представлении:

<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>

Анонимный тип и LINQ делают это намного более элегантным ИМХО. Без обид, Эш. :)

хороший ответ! Я надеялся, что кто-то будет использовать linq и SelectList :) Рад, что я сначала проверил здесь!

Pure.Krome 22.03.2009 05:50

ID = s дает мне DataTextField, а не значение? В чем может быть причина? Спасибо

Barbaros Alp 18.12.2009 22:09

Rune, я использовал тот же метод, и DropDownList ДЕЙСТВИТЕЛЬНО отображает, но когда он отправляет на сервер, он не сохраняет значение, которое я выбрал.

clockwiseq 23.11.2011 21:31

@BarbarosAlp Чтобы ID был числом, вам нужно преобразовать перечисление в int: select new { ID = (int)s, Name = s.ToString() };

Keith 02.12.2011 00:05

Этот ответ мне нравится больше всего из-за его простоты. Жаль, что вы не получили достаточного количества баллов, поскольку в выбранном ответе использовалось ваше решение.

anar khalilov 15.11.2013 13:07

@Keith, если вы используете дженерики вместо фиксированного enum, Visual Studio не позволит вам выполнить это приведение. Он сообщает вам Cannot convert type 'TEnum' to 'int'. :( (Я использую принятый код ответа, кстати)

Andrew 29.04.2015 07:24
Ответ принят как подходящий

Для MVC v5.1 используйте Html.EnumDropDownListFor

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

Для MVC v5 используйте EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

Для MVC 5 и ниже

Я свернул ответ Rune в метод расширения:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

Это позволяет писать:

ViewData["taskStatus"] = task.Status.ToSelectList();

автор: using MyApp.Common

У меня не получилось, не могли бы вы помочь. Когда я делаю Post.Post Type.To SelectList (); он не распознает расширение?

Barbaros Alp 18.12.2009 16:41

Я тоже не мог заставить это работать. Является ли статус вашим свойством Enum в классе задачи? Разве это не одно из перечисленных значений?

Daryl 05.07.2010 19:42

Большой! На вопросы выше, да, это одно из значений перечисления, которое становится «выбранным значением». Вы также можете: ((TypesEnum) typeId) .ToSelectList ();

Seba Illingworth 19.03.2011 05:29

убедитесь, что если вы еще не добавили пространство имен для своих помощников, вы добавляете его через 'using <namespace>;' директива в твоей бритве

TodK 28.03.2011 18:35

Одно предостережение: поскольку метод расширения не имеет ограничений, он будет расширять каждый тип. Это неизбежно, потому что вы не знаете, что такое перечислимые типы, и вы все равно не могли ограничить их (я считаю). Итак, вы обнаружите, что, например, int теперь имеет метод ToSelectList. Я совершил ту же ошибку и считаю, что по этой причине оно лучше в качестве расширения Html.

Rob Kent 19.04.2011 22:56

Вы можете немного ограничить его с помощью: where T: struct, IConvertible См.: stackoverflow.com/questions/79126/…

Richard Garside 17.05.2011 19:29

Это здорово. Если кто-то борется с реализацией, вот как я это сделал. Добавлен класс EnumHelpers в папку HtmlHelpers. Использовал приведенный выше код. Добавлено пространство имен в соответствии с рекомендацией @TodK: <add namespace = "xxx.HtmlHelpers" />. Затем я использовал его на такой странице с бритвой: @ Html.DropDownListFor (model => model.Status, @ Model.Status.ToSelectList ()) HTH

Jeff Borden 25.07.2012 23:28

Используется @ Html.DropDownListFor (model => model.SelectedCategory, Model.SelectedCategory.ToSelectList ()}, где SelectedCategory является типом Enum.

Per G 24.06.2013 16:56

Добавлены ограничения универсального типа из комментария Рикардо Нольде и Лизы к stackoverflow.com/a/79903/221708.

Daniel Schilling 19.07.2013 00:43

Обратите внимание, что в более новой версии ASP.NET MVC есть собственный способ: stackoverflow.com/a/22295360/1361084

Ofiris 28.01.2015 19:22

«Тип возврата 'System.Int64' не поддерживается. Имя параметра: выражение»

juFo 17.04.2018 12:51

Расширяя ответы Prize и Rune, если вы хотите, чтобы атрибут value элементов вашего списка выбора отображался на целочисленное значение типа Enumeration, а не на строковое значение, используйте следующий код:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if (!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

Вместо того, чтобы рассматривать каждое значение перечисления как объект TEnum, мы можем рассматривать его как объект, а затем преобразовать его в целое число, чтобы получить распакованное значение.

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

Обновление 23.10.12: Добавлен параметр универсального типа для базового типа и исправлена ​​проблема без компиляции, влияющая на .NET 4+.

Спасибо! Это был ответ, который мне был нужен. Я сохраняю целочисленное значение Enum в виде столбца в базе данных, и это решение, похоже, работает отлично.

grimus 11.08.2010 10:40

но что, если вы храните char, а не int? это мой случай. очевидно, я мог бы изменить (int) на (char), но как насчет того, чтобы сделать этот общий. как это сделать?

Stefanvds 21.09.2010 16:46

@Stefandvds Это отличный вопрос относительно приведения к правильному представленному типу. Судя по только что проведенным мною тестам, кажется, что единственный способ добиться этого - указать фактический тип в качестве другого параметра типа. ToSelectList<TEnum, TEnumValue>(this TEnum enumObj) { ... }

Nathan Taylor 21.09.2010 17:19

@Stefandvds Посмотреть этот вопрос.

Nathan Taylor 21.09.2010 18:11

Если значения вашего перечисления - int, вы можете просто использовать Value = Convert.ToInt32(e). (int)e не компилируется. :(

Andrew 29.04.2015 07:38

Решить проблему получения числа вместо текста с помощью метода расширения Prise.

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}

Это то, что я искал, хотя он оказался уродливее, чем я думал. Интересно, почему Visual Studio не позволяет напрямую транслировать e на int.

Andrew 29.04.2015 07:26

Или вы можете просто использовать ID = Convert.ToInt32(e).

Andrew 29.04.2015 07:39

Еще одно исправление этого метода расширения - текущая версия не выбирала текущее значение перечисления. Я исправил последнюю строчку:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }

Так что без функций расширения, если вы ищете простое и легкое ... Это то, что я сделал

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

где XXXXX.Sites.YYYY.Models.State - это перечисление

Возможно, лучше выполнить вспомогательную функцию, но когда времени мало, работа будет выполнена.

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

Johncl 23.09.2011 18:20

Должна иметься возможность передать второй параметр с выбранным значением новой функции SelectList (IEnumerable, object). Документация MSDN: msdn.microsoft.com/en-us/library/dd460123.aspx

Marty Trenouth 23.09.2011 21:26

Html.DropDownListFor требует только IEnumerable, поэтому альтернативой решению Prise является следующее. Это позволит вам просто написать:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[Где SelectedItemType - это поле в вашей модели типа ItemTypes, а ваша модель не имеет значения NULL]

Кроме того, вам действительно не нужно обобщать метод расширения, поскольку вы можете использовать enumValue.GetType () вместо typeof (T).

Обновлено: здесь также интегрировано решение Саймона и включен метод расширения ToDescription.

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

У меня не работает ('System.NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта.') ... Моя 'Модель' имеет значение null ... вероятно, имеет какое-то отношение к 'GetNonNullableModelType', который у Саймона включены

Learner 25.03.2012 00:31

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

Zaid Masud 26.03.2012 13:43

Что ж, я новичок в asp mvc, но у меня есть опыт работы с .Net. Спасибо, я изучу то, что вы предлагали. Кстати, ваше расширение ToDescription находится далеко за пределами Enum. Думаю, подходит для самого «Объекта». Это то, что я использовал, когда взял код Саймона и немного его очистил.

Learner 27.03.2012 00:05

@Cristi трудно понять, что вы имеете в виду под «далеко за пределами области Enum», но похоже, что вы говорите, что метод расширения ToDescription не строго типизирован для перечисления ItemTypes? Это сделано намеренно и делает метод расширения универсальным для всех перечислений. Если вы сравниваете его с универсальным методом расширения, у каждого подхода есть свои плюсы и минусы. В частности, если вы генерируете, вы не можете ограничить его только перечислениями.

Zaid Masud 27.03.2012 15:26

Во-первых, ваш код в порядке, вы не ошиблись. Просто я предпочитаю более общие и логичные вещи. Мое личное мнение состоит в том, что нет необходимости создавать это расширение для Enum, поскольку существует более общий объект (Enum: Object), к которому это расширение применяется лучше. Вы все равно можете использовать остальную часть кода, это расширение будет иметь более высокую адгезию, если будет «ToDescription (это значение объекта)». Теперь надежда прояснилась.

Learner 30.03.2012 15:45

Отлично, с благодарностью. Я изменил value.ToString, чтобы использовать расширение FromCamelCase в случае отсутствия описания. Вот как я катаюсь :)

Valamas 18.02.2013 05:41

Если вы хотите добавить поддержку локализации, просто измените метод s.toString () на что-то вроде этого:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

Здесь typeof (Resources) - это ресурс, который вы хотите загрузить, а затем вы получаете локализованную строку, также полезную, если ваш перечислитель имеет значения с несколькими словами.

Это моя версия вспомогательного метода. Я использую это:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

Вместо этого:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

Вот:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }

Я знаю, что опаздываю на вечеринку по этому поводу, но подумал, что вы можете найти этот вариант полезным, поскольку он также позволяет вам использовать описательные строки, а не константы перечисления в раскрывающемся списке. Для этого украсьте каждую запись перечисления атрибутом [System.ComponentModel.Description].

Например:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

Вот мой код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;

 ...

 private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        Type realModelType = modelMetadata.ModelType;

        Type underlyingType = Nullable.GetUnderlyingType(realModelType);
        if (underlyingType != null)
        {
            realModelType = underlyingType;
        }
        return realModelType;
    }

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        Type enumType = GetNonNullableModelType(metadata);
        IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

        IEnumerable<SelectListItem> items = from value in values
            select new SelectListItem
            {
                Text = GetEnumDescription(value),
                Value = value.ToString(),
                Selected = value.Equals(metadata.Model)
            };

        // If the enum is nullable, add an 'empty' item to the collection
        if (metadata.IsNullableValueType)
            items = SingleEmptyItem.Concat(items);

        return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    }

Затем вы можете сделать это в своем представлении:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

Надеюсь, это вам поможет!

** ИЗМЕНИТЬ 2014-ЯНВ-23: Microsoft только что выпустила MVC 5.1, в котором теперь есть функция EnumDropDownListFor. К сожалению, он, похоже, не соблюдает атрибут [Описание], поэтому приведенный выше код все еще остается в силе. См. Раздел Enum в примечания к выпуску Microsoft для MVC 5.1.

Обновление: он поддерживает атрибут Отображать[Display(Name = "Sample")], поэтому его можно использовать.

[Обновление - только что заметил это, и здесь код выглядит как расширенная версия кода: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/, с парой дополнений. Если так, то атрибуция будет казаться справедливой ;-)]

+1 Я нашел этот самый полезный из всех ответов здесь. Я смог превратить это в фрагмент кода, который можно использовать повторно. Спасибо!

Ed Charbeneau 19.07.2011 18:23

В Visual Studio есть странная ошибка, когда, если вы не ссылаетесь на System.Web.Mvc.Html, он говорит, что DropDownListFor не может быть найден, но не может решить эту проблему. Приходится вручную делать using System.Web.Mvc.Html;. Просто так ты знаешь.

Kezzer 27.10.2011 17:29

У меня есть вариант этого по сути, который мы используем во всех наших проектах: gist.github.com/1287511

kamranicus 09.01.2012 22:45

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

thd 23.03.2012 02:12

Отличное решение, спасибо, было бы еще лучше, если бы вы могли кэшировать результаты GetEnumDescription

M. Mennan Kara 20.08.2012 17:52

Предоставленный вами код не работает для MVC 4, ваш код просмотра выдает сообщение «Вызов неоднозначен для следующих методов или свойств», а затем перечисляет два длинных имени метода EnumDropDownListFor и свойства.

Marc 14.09.2012 22:05

Новый MVC 5.1 EnumDropDownListFor не использует [Description ("")], но использует [Display (Name = "")]! Наслаждаться :)

Supergibbs 28.02.2014 22:51

Красивый. Пришлось немного погуглить, чтобы найти, как все это собрать. stackoverflow.com/questions/10998827/…

Bjørn Otto Vasbotten 24.04.2014 00:58

Я думаю, что код Selected = value.Equals(metadata.Model) на самом деле не повлияет, потому что MVC будет отображать выбранное значение раскрывающегося списка в соответствии со значением свойства модели внутри переменной выражения.

BornToCode 23.11.2015 21:20

Взгляните на это: codeproject.com/Articles/776908/Dealing-with-Enum-in-MVC

Cas Bloem 19.01.2016 00:09

@Simon Goldstone: Спасибо за ваше решение, оно отлично подходит для моего случая. Проблема только в том, что мне пришлось переводить его на VB. Но теперь это сделано, и, чтобы сэкономить время других людей (на случай, если оно им понадобится), я помещаю его сюда:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .Text = GetEnumDescription(value),
                .Value = value.ToString(),
                .Selected = value.Equals(metaData.Model)
            }

        ' If the enum is nullable, add an 'empty' item to the collection
        If metaData.IsNullableValueType Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

Конец. Вы используете это так:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))

Вы также можете использовать мои пользовательские HtmlHelpers в Griffin.MvcContrib. Следующий код:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

Создает:

https://github.com/jgauffin/griffin.mvccontrib

Это ответы Rune & Prize, измененные для использования значения Enum int в качестве идентификатора.

Пример перечисления:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

Способ расширения:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

Пример использования:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

Не забудьте импортировать пространство имен, содержащее метод расширения

<%@ Import Namespace = "MyNamespace.LocationOfExtensionMethod" %>

Образец сгенерированного HTML:

<select id = "MyEnumList" name = "MyEnumList">
    <option value = "1">Movie</option>
    <option selected = "selected" value = "2">Game</option>
    <option value = "3">Book </option>
</select>

Обратите внимание, что элемент, который вы используете для вызова ToSelectList, является выбранным элементом.

Или вы можете просто использовать Id = Convert.ToInt32(e).

Andrew 29.04.2015 07:44

Лучшим решением, которое я нашел для этого, было объединение этот блог с Ответ Саймона Голдстоуна.

Это позволяет использовать перечисление в модели. По сути, идея состоит в том, чтобы использовать целочисленное свойство, а также перечисление, и имитировать целочисленное свойство.

Затем используйте атрибут [System.ComponentModel.Description] для аннотирования модели отображаемым текстом и используйте расширение «EnumDropDownListFor» в вашем представлении.

Это делает представление и модель очень удобочитаемыми и удобными в обслуживании.

Модель:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

Вид:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

Расширение (непосредственно из Ответ Саймона Голдстоуна, включено сюда для полноты):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
        {
            Type realModelType = modelMetadata.ModelType;

            Type underlyingType = Nullable.GetUnderlyingType(realModelType);
            if (underlyingType != null)
            {
                realModelType = underlyingType;
            }
            return realModelType;
        }

        private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

        public static string GetEnumDescription<TEnum>(TEnum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return value.ToString();
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
        {
            return EnumDropDownListFor(htmlHelper, expression, null);
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            Type enumType = GetNonNullableModelType(metadata);
            IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

            IEnumerable<SelectListItem> items = from value in values
                                                select new SelectListItem
                                                {
                                                    Text = GetEnumDescription(value),
                                                    Value = value.ToString(),
                                                    Selected = value.Equals(metadata.Model)
                                                };

            // If the enum is nullable, add an 'empty' item to the collection
            if (metadata.IsNullableValueType)
                items = SingleEmptyItem.Concat(items);

            return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
        }
    }
}

Это не работает, MVC 4 Razor. В представлении или во время выполнения error = "Вызов неоднозначен для следующих методов или свойств 'LDN.Extensions.MvcExtensions.EnumDropDownListFor <MyModel, LD‌ N.Models.YesPartialN‌ oEnum?> (System.Web.M‌ vc. HtmlHelper <MyMode‌ l>, System.Linq.Expressions.Expression <System.Func <MyModel, LDN.M odels.YesPartialNoEn‌ um? >>) 'и .... "и тот же самый метод с теми же реквизитами повторяется снова (здесь недостаточно символов).

Marc 15.09.2012 02:41

Это версия для Razor:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)

Это будет работать, только если ваше перечисление состоит из смежных значений, начинающихся с 0. Перечисление Flags не будет работать с этим. Тем не менее, творческое использование индексированного Select.

Suncat2000 21.11.2018 16:34

Я закончил тем, что создал методы расширения, чтобы сделать то, что, по сути, является здесь ответом accept. Последняя половина Gist посвящена конкретно Enum.

https://gist.github.com/3813767

Я очень опаздываю с этим, но я только что нашел действительно классный способ сделать это с помощью одной строки кода, если вы счастливы добавить пакет 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.DropDownListFor, используя это свойство в качестве источника.

+1 за использование кода Джона Скита :), шучу, хороший

Vamsi 08.02.2013 15:51

Вот лучшее инкапсулированное решение:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

Скажем, вот ваша модель:

Пример использования:

Сгенерированный пользовательский интерфейс:

И сгенерированный HTML

Снимок исходного кода вспомогательного расширения:

Вы можете скачать образец проекта по предоставленной мной ссылке.

Обновлено: вот код:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name = "TModel">The type of the model.</typeparam>
    /// <typeparam name = "TProperty">The type of the property.</typeparam>
    /// <param name = "htmlHelper">The HTML helper.</param>
    /// <param name = "expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name = "enumType">Type of the enum.</param>
    /// <param name = "selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}

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

Ben Mills 19.07.2013 00:31

Вызовите метод расширения как EnumDropDownListFor, а не DropDownListFor. Использование: -> @ Html.EnumDropDownListFor (x => x.Gender)

sandeep talabathula 13.07.2014 16:53

Для тех, кто хочет добавить еще один элемент «Пожалуйста, выберите» return htmlHelper.DropDownListFor (выражение, createSelectList (выражение.ReturnType, selected, firstElement), «Пожалуйста, выберите»);

Sandeep 09.08.2014 01:22

Работает отлично! Однако на странице Details DisplayFor () показывает выбранное значение перечисления вместо соответствующего описания. Я полагаю, это требует перегрузки DisplayFor () для типа перечисления. У кого-нибудь есть решение для этого?

corix010 21.01.2016 19:02

Основываясь на ответе Саймона, аналогичный подход состоит в том, чтобы получить значения Enum для отображения из файла ресурсов, а не в атрибуте описания внутри самого Enum. Это полезно, если ваш сайт должен отображаться более чем на одном языке, и если у вас должен быть определенный файл ресурсов для Enums, вы могли бы пойти на один шаг дальше и иметь только значения Enum в своем Enum и ссылаться на них из расширения с помощью такое соглашение, как [EnumName] _ [EnumValue] - в конечном итоге меньше набора текста!

Тогда расширение будет выглядеть так:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

Ресурсы в файле Enums.Resx выглядят как ItemTypes_Movie: Фильм

Еще одна вещь, которую я хотел бы сделать, это вместо того, чтобы вызывать метод расширения напрямую, я бы предпочел называть его с помощью @ Html.EditorFor (x => x.MyProperty) или, в идеале, просто иметь всю форму в одном аккуратном @ Html.EditorForModel (). Для этого я изменяю шаблон строки, чтобы он выглядел так

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

Если вас это интересует, я поместил гораздо более подробный ответ здесь, в своем блоге:

http://paulthecyclist.com/2013/05/24/enum-dropdown/

@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text = "Male",Value = "Male"},
 new ListItem{Text = "Female",Value = "Female"},
 new ListItem{Text = "--- Select -----",Value = "-----Select ----"}
}
)
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})

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

Andrew 30.04.2015 07:55

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

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

В вашем контроллере:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

В вашем представлении:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

Вспомогательный класс:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var fi = value.GetType().GetField(value.ToString());

        if (fi != null)
        {
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
        }

        return value.ToString();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}

1- Создайте свой ENUM

public enum LicenseType
{
    xxx = 1,
    yyy = 2
}

2- Создайте свой класс обслуживания

public class LicenseTypeEnumService
    {

        public static Dictionary<int, string> GetAll()
        {

            var licenseTypes = new Dictionary<int, string>();

            licenseTypes.Add((int)LicenseType.xxx, "xxx");
            licenseTypes.Add((int)LicenseType.yyy, "yyy");

            return licenseTypes;

        }

        public static string GetById(int id)
        {

            var q = (from p in this.GetAll() where p.Key == id select p).Single();
            return q.Value;

        }

    }

3- Установите ViewBag в вашем контроллере

var licenseTypes = LicenseTypeEnumService.GetAll();
ViewBag.LicenseTypes = new SelectList(licenseTypes, "Key", "Value");

4- Свяжите свой DropDownList

@Html.DropDownList("LicenseType", (SelectList)ViewBag.LicenseTypes)

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

Andrew 30.04.2015 07:56
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))

Хорошо! Как таким образом получить значение и текст из перечисления? Я имею в виду, что у меня есть SomeEnum {some1 = 1, some2 = 2} Мне нужно получить числа (1, 2) для значения и текст (some1, some2) для текста списка выбора

Dmitresky 05.03.2014 11:59

Теперь эта функция прямо из коробки поддерживается в версиях от MVC 5.1 до @Html.EnumDropDownListFor().

Проверьте следующую ссылку:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

Очень жаль, что Microsoft потребовалось 5 лет, чтобы реализовать такую ​​функцию, которая так востребована согласно результатам голосования выше!

В ASP.NET MVC 5.1 они добавили помощника EnumDropDownListFor(), поэтому нет необходимости в пользовательских расширениях:

Модель:

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

Вид:

@Html.EnumDropDownListFor(model => model.MyEnum)

Использование помощника по тегам (ASP.NET MVC 6):

<select asp-for = "@Model.SelectedValue" asp-items = "Html.GetEnumSelectList<MyEnum>()">

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

Kevin Heidt 29.03.2015 22:44

Что мне не нравится в EnumDropDownListFor (), так это то, что он сохраняет в БД значение int перечисления, а не текст, поэтому, если вы когда-либо решите добавить новый элемент перечисления, он обязательно должен быть в конце списка , чтобы не потерять связь сохраненных значений int в базе данных с исходными позициями элементов перечисления. Это ненужное ограничение, если текст сохранен. Кроме того, я предпочитаю смотреть на базу данных и видеть текст, а не на целые числа, в которых затем мне нужно искать текстовые значения в другом месте. В остальном этот html-помощник очень удобен в использовании.

Giovanni 22.05.2015 18:57

@Giovanni - вы можете указать свои числовые значения.

Tommy 24.01.2016 23:50

это еще не ужин enum [Flags] :(

mejiamanuel57 22.07.2016 05:46

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

King King 04.11.2016 11:30

Как определить дефолт? Пришлось использовать @Html.DropDownListFor(m => m.MyProperty, @Html.GetEnumSelectList(typeof(MyTypes.MyModel)))

MushyPeas 22.12.2016 15:31

Нашел ответ здесь. Однако некоторые из моих перечислений имеют атрибут [Description(...)], поэтому я изменил код, чтобы обеспечить его поддержку:

    enum Abc
    {
        [Description("Cba")]
        Abc,

        Def
    }


    public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
    {
        IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
            .Cast<TEnum>();

        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var value in values)
        {
            string text = value.ToString();

            var member = typeof(TEnum).GetMember(value.ToString());
            if (member.Count() > 0)
            {
                var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (customAttributes.Count() > 0)
                {
                    text = ((DescriptionAttribute)customAttributes[0]).Description;
                }
            }

            items.Add(new SelectListItem
            {
                Text = text,
                Value = value.ToString(),
                Selected = (value.Equals(selectedValue))
            });
        }

        return htmlHelper.DropDownList(
            name,
            items
            );
    }

Надеюсь, это поможет.

Я хочу вернуть член типа = DropdownList. Я хорошо разбираюсь в атрибуте Text = DescriptionAttribute, но мне трудно получить значение int из Value

RedBottleSanitizer 16.07.2019 23:55

Супер простой способ сделать это - без всяких расширений, которые кажутся излишними:

Ваше перечисление:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

Внутри вашего контроллера привяжите Enum к списку:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

После этого бросьте его в ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

Наконец, просто привяжите его к View:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

Это, безусловно, самый простой способ, который я нашел, и не требует никаких расширений или чего-то такого безумного.

ОБНОВИТЬ: см. Комментарий Эндрюса ниже.

Это работает, только если вы не присвоили своему перечислению никакого значения. Если бы у вас был Level1 = 1, то значение в раскрывающемся списке было бы "Level1" вместо 1.

Andrew 29.04.2015 07:43

Здесь вариант Мартина Фаартофта, где вы можете разместить собственные метки, которые удобны для локализации.

public static class EnumHtmlHelper
{
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj, Dictionary<int, string> customLabels)
        where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = e, Name = customLabels.First(x => x.Key == Convert.ToInt32(e)).Value.ToString() };

        return new SelectList(values, "Id", "Name", enumObj);
    }
}

Использование в поле зрения:

@Html.DropDownListFor(m => m.Category, Model.Category.ToSelectList(new Dictionary<int, string>() { 
          { 1, ContactResStrings.FeedbackCategory }, 
          { 2, ContactResStrings.ComplainCategory }, 
          { 3, ContactResStrings.CommentCategory },
          { 4, ContactResStrings.OtherCategory }
      }), new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Category)

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

Andrew 30.04.2015 07:58

Я сделал следующее и успешно работает:

  • В view.cshtml:

@model MyModel.cs

@Html.EnumDropDownListFor(m=>m.MyItemType )
  • В модели: MyModel.cs

public ItemTypes MyItemType { get; set; }

Вы просто продублировали ответ @Ofiris, и это работает только для ASP.NET MVC 5.1 и выше.

corix010 21.01.2016 19:21

В MVC4 я бы сделал это

@Html.DropDownList("RefType", new SelectList(Enum.GetValues(typeof(WebAPIApp.Models.RefType))), " Select", new { @class = "form-control" })

public enum RefType
    {
        Web = 3,
        API = 4,
        Security = 5,
        FE = 6
    }

    public class Reference
    {
        public int Id { get; set; }
        public RefType RefType { get; set; }
    }
        ////  ViewModel

        public class RegisterViewModel
          {

        public RegisterViewModel()
          {
              ActionsList = new List<SelectListItem>();
          }

        public IEnumerable<SelectListItem> ActionsList { get; set; }

        public string StudentGrade { get; set; }

           }

       //// Enum Class

        public enum GradeTypes
             {
               A,
               B,
               C,
               D,
               E,
               F,
               G,
               H
            }

         ////Controller action 

           public ActionResult Student()
               {
    RegisterViewModel vm = new RegisterViewModel();
    IEnumerable<GradeTypes> actionTypes = Enum.GetValues(typeof(GradeTypes))
                                         .Cast<GradeTypes>();                  
    vm.ActionsList = from action in actionTypes
                     select new SelectListItem
                     {
                         Text = action.ToString(),
                         Value = action.ToString()
                     };
              return View(vm);
               }

         ////// View Action

   <div class = "form-group">
                            <label class = "col-lg-2 control-label" for = "hobies">Student Grade:</label>
                            <div class = "col-lg-10">
                               @Html.DropDownListFor(model => model.StudentGrade, Model.ActionsList, new { @class = "form-control" })
                            </div>

Я хотел бы ответить на этот вопрос по-другому, когда пользователю не нужно ничего делать в выражении controller или Linq. Сюда...

У меня ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

Теперь я могу просто создать dropdown, используя этот enum.

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

ИЛИ ЖЕ

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

Если вы хотите выбрать индекс, попробуйте это

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

Здесь я использовал AccessLevelEnum.NoAccess в качестве дополнительного параметра для выбора раскрывающегося списка по умолчанию.

В .NET Core вы можете просто использовать это:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())

Или с помощью тега-помощника <select asp-for = "Model.Foo" class = "form-control" asp-items = "@Html.GetEnumSelectList<MyEnum>()"></select>.

Pascal R. 07.04.2020 15:29

да, я бы сказал, помощники по тегам даже лучше, поскольку формат ближе к чистому HTML;)

GoldenAge 07.04.2020 16:35

Также вы можете сделать это @ Html.DropDownListFor (x => x.Foo, Html.GetEnumSelectList (typeof (FooEnum)))

Fereydoon Barikzehy 09.05.2020 01:20

Просто и мило. ТЫ!

Pratap Singh Mehra 01.07.2020 22:01

отличный ответ. Искал, чтобы не нужно было создавать собственный метод для этого

Kolob Canyon 16.09.2020 00:11

Другие вопросы по теме