[C#] ASP.NET MVC의 열거 형에서 드롭 다운 목록을 어떻게 만듭니 까?

Html.DropDownList확장 방법 을 사용하려고하는데 열거 형과 함께 사용하는 방법을 알 수 없습니다.

다음과 같은 열거 형이 있다고 가정 해 봅시다.

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

Html.DropDownList확장 방법을 사용하여 이러한 값으로 드롭 다운을 만드는 방법은 무엇입니까?

아니면 단순히 for 루프를 만들고 Html 요소를 수동으로 만드는 것이 가장 좋은 방법입니까?



답변

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


답변

나는 이것에 대해 파티에 늦었다는 것을 알고 있지만,이 변형은 드롭 다운에서 열거 상수 대신 설명 문자열을 사용할 수 있기 때문에이 변형이 유용하다고 생각했습니다. 이렇게하려면 각 열거 항목을 [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-JAN-23 : Microsoft는 이제 EnumDropDownListFor 기능이있는 MVC 5.1을 출시했습니다. 슬프게도 [Description] 속성을 준수하지 않는 것 같으므로 위의 코드는 여전히 유효 합니다. MVC 5.1에 대한 Microsoft 릴리스 정보의 Enum 섹션을 참조 하십시오.

업데이트 : Display 속성을 지원 [Display(Name = "Sample")]하므로 사용할 수 있습니다.

[업데이트-방금 확인한 코드는 다음 코드의 확장 된 버전입니다. https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a- dropdownlist-helper-for-enums / , 몇 가지 추가 사항이 있습니다. 그렇다면 기여는 공평 해 보일 것입니다 ;-)]


답변

에서 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>()">


답변

나는 같은 문제에 부딪 쳤고,이 질문을 발견했으며, Ash가 제공 한 솔루션이 내가 찾고있는 솔루션이 아니라고 생각했다. 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보기에서 익숙한 것처럼 사용할 수 있는 좋은 ol ‘ 을 만듭니다 .

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

익명 유형과 LINQ는 이것을 훨씬 더 우아하게 만듭니다. 범죄 의도가 없습니다, 애쉬 🙂


답변

더 나은 캡슐화 솔루션은 다음과 같습니다.

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

모델이 여기 있다고 가정하십시오.

여기에 이미지 설명을 입력하십시오

샘플 사용법 :

여기에 이미지 설명을 입력하십시오

생성 된 UI :
여기에 이미지 설명을 입력하십시오

그리고 생성 된 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();
    }
}


답변

Html.DropDownList의 경우 IEnumerable 만 필요하므로 Prise 솔루션의 대안은 다음과 같습니다. 이를 통해 간단하게 작성할 수 있습니다.

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

[SelectedItemType이 ItemTypes 유형의 모델에 대한 필드이고 모델이 null이 아닌 경우]

또한 typeof (T) 대신 enumValue.GetType ()을 사용할 수 있으므로 확장 메서드를 실제로 일반화 할 필요는 없습니다.

편집 : 여기에 Simon의 솔루션도 통합되었으며 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();
    }
}


답변

간단하고 쉬운 방법을 찾고 있다면 확장 기능이 없으면 .. 이것이 내가 한 일입니다.

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

여기서 XXXXX.Sites.YYYY.Models.State는 열거 형입니다.

아마도 도우미 기능을 수행하는 것이 좋을지 모르지만 시간이 짧으면 작업이 완료됩니다.