MVC3 Razor DropDownListFor Enums

jor*_*cke 84 c# razor asp.net-mvc-3

试图让我的项目更新到MVC3,我找不到的东西:

我有一个简单的ENUMS数据类型:

public enum States()
{
  AL,AK,AZ,...WY
}
Run Code Online (Sandbox Code Playgroud)

在我的包含此数据类型的模型视图中,我想将其用作DropDown/SelectList:

public class FormModel()
{
    public States State {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

非常简单:当我为这个分部类使用自动生成视图时,它忽略了这种类型.

我需要一个简单的选择列表,当我通过我的AJAX - JSON POST方法点击提交和处理时,将枚举的值设置为所选项.

而不是视图(???!):

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

提前感谢您的建议!

小智 198

我在这里找到了一种更简单的解决方案: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);
}   }   }
Run Code Online (Sandbox Code Playgroud)

剃刀中的一行会做到:

@Html.DropDownListFor(model => model.State, new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States))))
Run Code Online (Sandbox Code Playgroud)

您还可以在链接文章中找到使用扩展方法执行此操作的代码.

  • 我认为这个应该被标记为解决方案.最好的不是复杂性,而是简单. (6认同)
  • 对于看起来像DropDowList版本的人(像我一样):@ Html.DropDownList("listName",新的SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States)))) (3认同)
  • @triangulito这根本不是问题:)`@ Html.DropDownListFor(model => model.State,new SelectList(Enum.GetValues(typeof(MyNamespace.Enums.States)),model.State))` (3认同)
  • @JonEgerton如果你的意思和我一样,那么我同意.如果您想显示枚举+描述+图像,您将失去Mike McLaughlin的解决方案. (2认同)

jga*_*fin 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用它作为:

Html.EnumDropDownListFor(m => m.YourEnum);
Run Code Online (Sandbox Code Playgroud)

更新

我已经创建了替代的Html助手.您需要做的就是更改您的baseviewpage views\web.config.

有了他们,你可以这样做:

@Html2.DropDownFor(m => m.YourEnum);
@Html2.CheckboxesFor(m => m.YourEnum);
@Html2.RadioButtonsFor(m => m.YourEnum);
Run Code Online (Sandbox Code Playgroud)

更多信息:http://blog.gauffin.org/2011/10/first-draft-of-my-alternative-html-helpers/

  • @filu @jordan添加`using System.Web.Mvc.Html;`因为你需要访问[`SelectExtensionsClass`](http://msdn.microsoft.com/en-us/library/system.web.mvc. html.selectextensions.aspx) (9认同)
  • @Para我遇到了同样的问题,所选的值在视图中没有出现.(我不得不为`Enum.GetName(enumType,item)`改变`((int)item).ToString()`以使'SelectListItem`正确保存为选中,但它仍然不起作用) (3认同)

Vin*_*els 23

ASP.NET MVC 5.1(RC1)开始,EnumDropDownListFor默认包含作为扩展方法HtmlHelper.


sjm*_*ett 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;
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

然后生成下拉列表就像这样简单:

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

LINQ不漂亮吗?


小智 12

我能够在一个班轮里做到这一点.

@Html.DropDownListFor(m=>m.YourModelProperty,new SelectList(Enum.GetValues(typeof(YourEnumType))))
Run Code Online (Sandbox Code Playgroud)


Jon*_*ton 7

基于@jgauffin接受的答案,我创建了自己的版本EnumDropDownListFor,它处理选择项目的问题.

这个问题在另一个SO答案中有详细说明:并且基本上归结为对不同重载的行为的误解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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里写了这篇文章.