我正在尝试使用Html。下拉列表扩展方法,但不知道如何与枚举一起使用它。

假设我有一个这样的枚举:

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

我如何去创建一个下拉与这些值使用Html。下拉列表扩展方法?

或者我最好的办法是简单地创建一个for循环并手动创建Html元素?


当前回答

我找到的最好的解决办法就是把这个博客和西蒙·戈德斯通的答案结合起来。

这允许在模型中使用枚举。从本质上讲,这个想法是使用整数属性和枚举,并模拟整数属性。

然后使用[System.ComponentModel。属性用于用你的显示文本注释模型,并在你的视图中使用“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)
//...
}

扩展(直接来自Simon Goldstone的回答,为完整起见,此处包含):

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);
        }
    }
}

其他回答

        ////  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>

您希望使用类似Enum的东西。getvalue

所以没有扩展函数,如果你正在寻找简单和容易..这就是我所做的

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

where XXXXX.Sites.YYYY.Models.State是enum

也许做辅助函数更好,但是当时间很短的时候,这将完成工作。

现在这个特性在MVC 5.1中通过@Html.EnumDropDownListFor()得到了开箱即用的支持。

查看以下链接:

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

根据上面的投票,微软花了5年的时间来实现这样一个如此受欢迎的功能,真是太遗憾了!

我知道我在这方面已经晚了,但我认为您可能会发现这个变体很有用,因为它还允许您在下拉列表中使用描述性字符串而不是枚举常量。为此,使用[System.ComponentModel]装饰每个枚举条目。描述]属性。

例如:

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年1月23日:微软刚刚发布了MVC 5.1,现在有一个EnumDropDownListFor功能。不幸的是,它似乎不尊重[Description]属性,所以上面的代码仍然有效。请参阅微软MVC 5.1发布说明中的Enum部分。

更新:它支持显示属性[Display(Name = "Sample")],所以你可以使用它。

[更新-刚刚注意到这一点,代码看起来像一个扩展版本的代码:https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums/,增加了一些内容。如果是这样,归因似乎是公平的;-)]