MVC3 Razor DropDownListFor 열거 형


84

내 프로젝트를 MVC3로 업데이트하려고 시도했지만 찾을 수 없습니다.

ENUMS의 간단한 데이터 유형이 있습니다.

public enum States()
{
  AL,AK,AZ,...WY
}

이 데이터 유형을 포함하는 모델의보기에서 DropDown / SelectList로 사용하고 싶습니다.

public class FormModel()
{
    public States State {get; set;}
}

매우 간단합니다.이 부분 클래스에 대해 자동 생성보기를 사용하려고하면이 유형을 무시합니다.

AJAX-JSON POST 메서드를 통해 제출 및 처리를 누를 때 열거 형 값을 선택한 항목으로 설정하는 간단한 선택 목록이 필요합니다.

그리고보기 (???!)보다 :

    <div class="editor-field">
        @Html.DropDownListFor(model => model.State, model => model.States)
    </div>

조언에 미리 감사드립니다!


8
이 스레드를 발견하고 MVC 5.1 이상을 사용하는 모든 사람을 위해 도우미 메서드 @ Html.EnumDropDownListFor ()가 이제 MVC에 내장되어 있습니다. asp.net/mvc/overview/releases/mvc51-release-notes
mecsco

답변:


55

내 프로젝트를 위해 방금 만들었습니다. 아래 코드는 내 도우미 클래스의 일부이며 필요한 모든 메서드를 얻었 으면합니다. 작동하지 않는 경우 댓글을 작성하고 다시 확인하겠습니다.

public static class SelectExtensions
{

    public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
    }

    public static SelectList ToSelectList(Type enumType, string selectedItem)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
            var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
            var listItem = new SelectListItem
                {
                    Value = ((int)item).ToString(),
                    Text = title,
                    Selected = selectedItem == ((int)item).ToString()
                };
            items.Add(listItem);
        }

        return new SelectList(items, "Value", "Text", selectedItem);
    }
}

다음과 같이 사용하십시오.

Html.EnumDropDownListFor(m => m.YourEnum);

최신 정보

대체 Html 도우미를 만들었습니다. 그것들을 사용하기 위해해야 ​​할 일은에서 baseviewpage를 변경하는 것입니다 views\web.config.

그들과 함께 할 수 있습니다.

@Html2.DropDownFor(m => m.YourEnum);
@Html2.CheckboxesFor(m => m.YourEnum);
@Html2.RadioButtonsFor(m => m.YourEnum);

추가 정보 : http://blog.gauffin.org/2011/10/first-draft-of-my-alternative-html-helpers/


1
좋습니다. 어느 쪽이든 잘 작동합니다. 컴파일 오류가 하나만 발생합니다. 41 행 : return htmlHelper.DropDownList (inputName, ToSelectList (typeof (TProperty), value.ToString ())); 'System.Web.Mvc.HtmlHelper <TModel>'에 'DropDownList'에 대한 정의가 포함되어 있지 않으며 'System.Web.Mvc.HtmlHelper <TModel>'유형의 첫 번째 인수를 허용하는 확장 메서드 'DropDownList'를 찾을 수 없습니다 ( 당신은 using 지시문 또는 어셈블리 참조가)?
jordan.baucke

1
@jordan 같은 오류가 있습니다. 문제를 해결할 수 있었습니까?
SF Developer

9
@filu 추가 @jordan using System.Web.Mvc.Html;사용자가 액세스 할 필요가로SelectExtensionsClass
사이먼 Hartcher

3
@Para 동일한 문제가 발생합니다. 선택한 값이보기에서 선택된 것으로 나타나지 않습니다. (I 변경했다 ((int)item).ToString()위해 Enum.GetName(enumType, item)가져 오기하는 SelectListItem올바르게 선택으로 저장,하지만 여전히 작동하지 않습니다)
페르난도 네이라

1
DropDownList 오버로드의 동작에 대한 오해에서 비롯된 선택 문제를 다루는 답변을 아래에 추가했습니다.
Jon Egerton

199

여기에 대한 더 간단한 해결책을 찾았습니다. http://coding-in.net/asp-net-mvc-3-method-extension/

using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace EnumHtmlHelper.Helper
{    
    public static class EnumDropDownList
    {
        public static HtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression, string firstElement)
        {
            var typeOfProperty = modelExpression.ReturnType;
            if(!typeOfProperty.IsEnum)
                throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));     
            var enumValues = new SelectList(Enum.GetValues(typeOfProperty));
            return htmlHelper.DropDownListFor(modelExpression, enumValues, firstElement);
}   }   }

면도기의 한 줄이이를 수행합니다.

@Html.DropDownListFor(model => model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States))))

링크 된 문서에서 확장 메서드를 사용하여 수행하는 코드를 찾을 수도 있습니다.


6
나는 이것이 해결책으로 표시되어야한다고 생각한다. 최고는 복잡성이 아니라 단순함으로 표시됩니다.
스크립트의 제왕

3
DropDowList 버전 (나와 같은)을 찾는 사람들을 위해 : @ Html.DropDownList ( "listName", new SelectList (Enum.GetValues ​​(typeof (MyNamespace.Enums.States))))
dstr

2
@JonEgerton 저와 같은 뜻이라면 동의합니다. 열거 형 + 설명 + 이미지를 표시하려면 Mike McLaughlin의 솔루션으로 손실됩니다.
Elisabeth

1
이 솔루션에서 찾은 유일한 문제는로드 할 때 선택한 값을 올바르게 매핑하지 않는다는 것입니다. 그 외에도 꽤 좋습니다.
triangulito

3
@triangulito 이것은 전혀 문제가되지 않습니다 :)@Html.DropDownListFor(model => model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States)),model.State))
VladL


17

정말 간단한 것을 원한다면 데이터베이스에 상태를 저장하는 방법에 따라 다른 방법이 있습니다.

다음과 같은 엔티티가있는 경우 :

public class Address
{
     //other address fields

     //this is what the state gets stored as in the db
     public byte StateCode { get; set; }

     //this maps our db field to an enum
     public States State
     {
         get
         {
             return (States)StateCode;
         }
         set
         {
             StateCode = (byte)value;
         }
     }
}

그런 다음 드롭 다운을 생성하는 것은 다음과 같이 쉽습니다.

@Html.DropDownListFor(x => x.StateCode,
    from State state in Enum.GetValues(typeof(States))
    select new SelectListItem() { Text = state.ToString(), Value = ((int)state).ToString() }
);

LINQ가 예쁘지 않습니까?


모델 또는 뷰에서 상태 열거를 어디에 정의합니까?
superartsy

모델에서, 그것은 모델 클래스에 의해 사용되는
sjmeverett

1
@stewartml 내 ViewModel에 enum 속성 + "SelectedCodeProperty"가 있으면이 속성은 게시물에서 너무 많은 속성입니다. 선택한 값으로 열거 형이 서버 + 항목 값으로 다시 게시되지 않는 이유는 무엇입니까?
Elisabeth

13

나는 이것을 하나의 라이너로 할 수 있었다.

@Html.DropDownListFor(m=>m.YourModelProperty,new SelectList(Enum.GetValues(typeof(YourEnumType))))

8

@jgauffin의 수락 된 답변을 기반으로 EnumDropDownListFor항목 선택 문제를 다루는 자체 버전을 만들었습니다 .

문제는 여기다른 SO 답변에 자세히 설명되어 있으며 기본적으로 .NET의 다양한 과부하 동작에 대한 오해로 인한 것입니다 DropDownList.

내 전체 코드 ( htmlAttributes등에 대한 오버로드 포함) 는 다음과 같습니다.

public static class EnumDropDownListForHelper
{

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

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            object htmlAttributes
        ) where TModel : class
    {
        return EnumDropDownListFor<TModel, TProperty>(
                            htmlHelper, expression, null, htmlAttributes);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            IDictionary<string, object> htmlAttributes
        ) where TModel : class
    {
        return EnumDropDownListFor<TModel, TProperty>(
                            htmlHelper, expression, null, htmlAttributes);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            string optionLabel
        ) where TModel : class
    {
        return EnumDropDownListFor<TModel, TProperty>(
                            htmlHelper, expression, optionLabel, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            string optionLabel, 
            IDictionary<string,object> htmlAttributes
        ) where TModel : class
    {
        string inputName = GetInputName(expression);
        return htmlHelper.DropDownList(
                            inputName, ToSelectList(typeof(TProperty)), 
                            optionLabel, htmlAttributes);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper, 
            Expression<Func<TModel, TProperty>> expression, 
            string optionLabel, 
            object htmlAttributes
        ) where TModel : class
    {
        string inputName = GetInputName(expression);
        return htmlHelper.DropDownList(
                            inputName, ToSelectList(typeof(TProperty)), 
                            optionLabel, htmlAttributes);
    }


    private static string GetInputName<TModel, TProperty>(
            Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression 
                            = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString()
                    .Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression 
                            = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }


    private static SelectList ToSelectList(Type enumType)
    {
        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var item in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(item.ToString());
            var attribute = fi.GetCustomAttributes(
                                       typeof(DescriptionAttribute), true)
                                  .FirstOrDefault();
            var title = attribute == null ? item.ToString() 
                              : ((DescriptionAttribute)attribute).Description;
            var listItem = new SelectListItem
            {
                Value = item.ToString(),
                Text = title,
            };
            items.Add(listItem);
        }

        return new SelectList(items, "Value", "Text");
    }
}

여기 내 블로그 에이 글을 올렸습니다 .


1
이것은 내 열거에 대한 관련 값을 올바르게 미리 선택하는 유일한 솔루션입니다. 감사!
Edwin Groenendaal

대박. 이것은 확실히 받아 들여지는 대답이어야합니다. 작동합니다. 받아 들여진 대답은 그렇지 않습니다.
neminem 2014

3

이것은 enum에서 int 값을 선택하는 데 도움이 될 것입니다. Here SpecTypeis an intfield ... and enmSpecTypeis an enum.

@Html.DropDownList(
    "SpecType", 
     YourNameSpace.SelectExtensions.ToSelectList(typeof(NREticaret.Core.Enums.enmSpecType), 
     Model.SpecType.ToString()), "Tip Seçiniz", new 
     { 
         gtbfieldid = "33", 
         @class = "small" 
     })

3

나를 위해 조금 더 잘 작동하도록 SelectList 메서드를 다음과 같이 변경했습니다. 아마도 다른 사람들에게 유용 할 것입니다.

public static SelectList ToSelectList<T>(T selectedItem)
        {
            if (!typeof(T).IsEnum) throw new InvalidEnumArgumentException("The specified type is not an enum");

            var selectedItemName = Enum.GetName(typeof (T), selectedItem);
            var items = new List<SelectListItem>();
            foreach (var item in Enum.GetValues(typeof(T)))
            {
                var fi = typeof(T).GetField(item.ToString());
                var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();

                var enumName = Enum.GetName(typeof (T), item);
                var title = attribute == null ? enumName : ((DescriptionAttribute)attribute).Description;

                var listItem = new SelectListItem
                {
                    Value = enumName,
                    Text = title,
                    Selected = selectedItemName == enumName
                };
                items.Add(listItem);
            }

            return new SelectList(items, "Value", "Text");
        }

3
    public enum EnumStates
    {
        AL = 0,
        AK = 1,
        AZ = 2,
        WY = 3
    }


@Html.DropDownListFor(model => model.State, (from EnumStates e in Enum.GetValues(typeof(EnumStates))
                                                               select new SelectListItem { Value = ((int)e).ToString(), Text = e.ToString() }), "select", new { @style = "" })
                @Html.ValidationMessageFor(model => model.State)  //With select



//Or


@Html.DropDownListFor(model => model.State, (from EnumStates e in Enum.GetValues(typeof(EnumStates))
                                                               select new SelectListItem { Value = ((int)e).ToString(), Text = e.ToString() }), null, new { @style = "" })
                @Html.ValidationMessageFor(model => model.State)   //With out select

EnumState는 어디에 정의합니까?
superartsy

상단에 u는 그것을 볼 수 있습니다 ... 공공 열거 EnumStates을
Thulasiram

2

Mike의 것과 동일 (긴 응답 사이에 묻혀 있음)

model.truckimagelocation은 TruckImageLocation 열거 형의 클래스 인스턴스 속성입니다.

@Html.DropDownListFor(model=>model.truckimagelocation,Enum.GetNames(typeof(TruckImageLocation)).ToArray().Select(f=> new SelectListItem() {Text = f, Value = f, Selected = false}))

2

이것은 모든 Enum에 사용되는 가장 일반적인 코드입니다.

public static class UtilitiesClass
{

    public static SelectList GetEnumType(Type enumType)
    {
        var value = from e in Enum.GetNames(enumType)
                    select new
                    {
                        ID = Convert.ToInt32(Enum.Parse(enumType, e, true)),
                        Name = e
                    };
        return new SelectList(value, "ID", "Name");
    }
}

조치 방법

ViewBag.Enum= UtilitiesClass.GetEnumType(typeof (YourEnumType));

View.cshtml

 @Html.DropDownList("Type", (IEnumerable<SelectListItem>)ViewBag.Enum, new { @class = "form-control"})

1

모델에서 열거 형을 사용할 수 있습니다.

당신의 열거 형

public enum States()
{
  AL,AK,AZ,...WY
}

모델을 만들다

public class enumclass
{
public States statesprop {get; set;}
}

보기에

@Html.Dropdownlistfor(a=>a.statesprop)

최신 질문 답변 kar.
Anup 2014.01.15

1

MVC5에서 가장 쉬운 대답은 Define Enum입니다.

public enum ReorderLevels {
          zero = 0,
            five = 5,
            ten = 10,
            fifteen = 15,
            twenty = 20,
            twenty_five = 25,
            thirty = 30
        }

보기에서 바인딩 :

        <div class="form-group">
            <label>Reorder Level</label>
            @Html.EnumDropDownListFor(m => m.ReorderLevel, "Choose Me", new { @class = "form-control" })
        </div>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.