在 MVC 4 中将枚举绑定到 DropDownList? [复制]

Posted

技术标签:

【中文标题】在 MVC 4 中将枚举绑定到 DropDownList? [复制]【英文标题】:Binding an Enum to a DropDownList in MVC 4? [duplicate] 【发布时间】:2013-06-21 06:43:48 【问题描述】:

我一直在发现将 Enums 绑定到 DropDowns 的常用方法是通过辅助方法,这对于这样一个看似简单的任务来说似乎有点霸道。

在 ASP.Net MVC 4 中将枚举绑定到 DropDownLists 的最佳方法是什么?

【问题讨论】:

@Sheridan 有点晚了,你不同意吗? 不,我完全不同意。在我看到你的问题之前,我不可能将它标记为重复,对吗?如果您对此有疑问,也许您应该阅读 Stack Overflow 帮助中心的 Why are some questions marked as duplicate? 页面,而不是留下毫无意义的 cmets? 【参考方案1】:

你可以这样做:

@html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem  Text = e ))

【讨论】:

谢谢。要包含枚举的 int 值,只需像这样扩展它:... Text = e, Value = ((int)Enum.Parse(typeof(UngKlub.Web.Models.Member.GenderEnum), e)).ToString() )) 如果您希望使用带有 [FLags] 的枚举,这是完美的解决方案【参考方案2】:

我认为这是唯一(干净)的方式,很遗憾,但至少有一些选择。我建议看看这个博客:http://paulthecyclist.com/2013/05/24/enum-dropdown/

对不起,这里复制太长了,但要点是他为此创建了一个新的 HTML 辅助方法。

所有源代码都可以在GitHub上找到。

【讨论】:

这个答案的要点在这个 SO 问题中得到了回答:***.com/questions/388483/… 以及这个问题的许多其他解决方案。 如果有人感兴趣(我知道 OP 指定 MVC 4)MVC 5.1 支持枚举:asp.net/mvc/overview/releases/mvc51-release-notes#Enum 这里有更好的解决方案。 ***.com/questions/388483/… 正如伯纳德所说,MVC5.1 现在涵盖了这一点,如果您能够使用该版本。我根据我之前的一篇文章创建了一个新的博客条目paulthecyclist.com/2014/04/03/enum-dropdown-mvc5-1,展示了一种可以利用它并且仍然从 resx 文件中获取下拉值的方法。 paulthecyclist 的帖子非常干净且易于理解。检查 github repo 也肯定。感谢资源。【参考方案3】:

自 MVC 5.1 起,框架就支持枚举:

@Html.EnumDropDownListFor(m => m.Palette)

可以自定义显示的文字:

public enum Palette

    [Display(Name = "Black & White")]
    BlackAndWhite,

    Colour

MSDN 链接:http://www.asp.net/mvc/overview/releases/mvc51-release-notes#Enum

【讨论】:

完美且易于使用:)【参考方案4】:

在我的控制器中:

var feedTypeList = new Dictionary<short, string>();
foreach (var item in Enum.GetValues(typeof(FeedType)))

    feedTypeList.Add((short)item, Enum.GetName(typeof(FeedType), item));

ViewBag.FeedTypeList = new SelectList(feedTypeList, "Key", "Value", feed.FeedType);

在我看来:

@Html.DropDownList("FeedType", (SelectList)ViewBag.FeedTypeList)

【讨论】:

当我在下拉列表中执行编辑操作时未选择值绑定?请帮忙【参考方案5】:

PaulTheCyclist 的解决方案是正确的。但我不会使用 RESX(我必须为每个新枚举添加一个新的 .resx 文件??)

这是我的 HtmlHelper 表达式:

public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TEnum>> expression, object attributes = null)

    //Get metadata from enum
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var enumType = GetNonNullableModelType(metadata);
    var values = Enum.GetValues(enumType).Cast<TEnum>();

    //Convert enumeration items into SelectListItems
    var items =
        from value in values
        select new SelectListItem
        
            Text = value.ToDescription(),
            Value = value.ToString(),
            Selected = value.Equals(metadata.Model)
        ;

    //Check for nullable value types
    if (metadata.IsNullableValueType)
    
        var emptyItem = new List<SelectListItem>
        
            new SelectListItem Text = string.Empty, Value = string.Empty
        ;
        items = emptyItem.Concat(items);
    

    //Return the regular DropDownlist helper
    return htmlHelper.DropDownListFor(expression, items, attributes);

这是我声明我的枚举的方式:

[Flags]
public enum LoanApplicationType

    [Description("Undefined")]
    Undefined = 0,

    [Description("Personal Loan")]
    PersonalLoan = 1,

    [Description("Mortgage Loan")]
    MortgageLoan = 2,

    [Description("Vehicle Loan")]
    VehicleLoan = 4,

    [Description("Small Business")]
    SmallBusiness = 8,

这是来自 Razor 视图的调用:

<div class="control-group span2">
    <div class="controls">
        @Html.EnumDropDownListFor(m => m.LoanType, new  @class = "span2" )
    </div>
</div>

@Model.LoanType 是 LoanApplicationType 类型的模型属性

更新:抱歉,忘记包含辅助函数 ToDescription() 的代码

/// <summary>
/// Returns Description Attribute information for an Enum value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToDescription(this Enum value)

    if (value == null)
    
        return string.Empty;
    
    var attributes = (DescriptionAttribute[]) value.GetType().GetField(
        Convert.ToString(value)).GetCustomAttributes(typeof (DescriptionAttribute), false);
    return attributes.Length > 0 ? attributes[0].Description : Convert.ToString(value);

【讨论】:

嗨,如果您要使用基于我的博客的解决方案,您的所有枚举只需要一个 resx 文件,并且只需使用约定来区分枚举。例如,如果你有两个枚举,颜色和数字说。一些 resx 条目的名称可能如下:Colour_Blue、Colour_Red、Colour_White、LoanApplicationType_Undefined、LoanApplicationType_Personal。如果您的 Web 应用程序不需要考虑本地化,Description 属性可以正常工作 我想如果您需要针对多种语言进行本地化,这是有道理的。我不得不使用 RESX 文件的时候,我通常使用自定义 DataAnnotationAttribute 来装饰枚举,并直接在枚举上设置资源文件条目。但我想你的方法会更舒服。我会在不久的将来尝试一下(谢谢)【参考方案6】:

从技术上讲,您不需要辅助方法,因为 Html.DropdownListFor 只需要 SelectListIenumerable&lt;SelectListItem&gt;。您可以将您的枚举转换为这样的输出并以这种方式提供。

我使用静态库方法将枚举转换为List&lt;SelectListItem&gt;,并带有一些参数/选项:

public static List<SelectListItem> GetEnumsByType<T>(bool useFriendlyName = false, List<T> exclude = null,
    List<T> eachSelected = null, bool useIntValue = true) where T : struct, IConvertible

    var enumList = from enumItem in EnumUtil.GetEnumValuesFor<T>()
                    where (exclude == null || !exclude.Contains(enumItem))
                    select enumItem;

    var list = new List<SelectListItem>();

    foreach (var item in enumList)
    
        var selItem = new SelectListItem();

        selItem.Text = (useFriendlyName) ? item.ToFriendlyString() : item.ToString();
        selItem.Value = (useIntValue) ? item.To<int>().ToString() : item.ToString();

        if (eachSelected != null && eachSelected.Contains(item))
            selItem.Selected = true;

        list.Add(selItem);
    

    return list;


public static class EnumUtil

    public static IEnumerable<T> GetEnumValuesFor<T>()
    
        return Enum.GetValues(typeof(T)).Cast<T>();
    
    // other stuff in here too...



/// <summary>
/// Turns Camelcase or underscore separated phrases into properly spaces phrases
/// "DogWithMustard".ToFriendlyString() == "Dog With Mustard"
/// </summary>
public static string ToFriendlyString(this object o)

    var s = o.ToString();
    s = s.Replace("__", " / ").Replace("_", " ");

    char[] origArray = s.ToCharArray();
    List<char> newCharList = new List<char>();

    for (int i = 0; i < origArray.Count(); i++)
    
        if (origArray[i].ToString() == origArray[i].ToString().ToUpper())
        
            newCharList.Add(' ');
        
        newCharList.Add(origArray[i]);
    

    s = new string(newCharList.ToArray()).TrimStart();
    return s;

您的 ViewModel 可以传入您想要的选项。这是一个相当复杂的:

public IEnumerable<SelectListItem> PaymentMethodChoices 
 
    get 
     
        var exclusions = new List<Membership.Payment.PaymentMethod>  Membership.Payment.PaymentMethod.Unknown, Membership.Payment.PaymentMethod.Reversal ;
        var selected = new List<Membership.Payment.PaymentMethod>  this.SelectedPaymentMethod ;
        return GetEnumsByType<Membership.Payment.PaymentMethod>(useFriendlyName: true, exclude: exclusions, eachSelected: selected); 
    

因此,您将 View 的 DropDownListIEnumerable&lt;SelectListItem&gt; 属性关联起来。

【讨论】:

【参考方案7】:

扩展 html 帮助器效果很好,但是如果您希望能够根据 DisplayAttribute 映射更改下拉值的文本,那么您需要像这样修改它,

(在 MVC 5.1 之前执行此操作,它包含在 5.1+ 中)

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 = enumValues.Select(item =>
    
        var type = item.GetType();
        var member = type.GetMember(item.ToString());
        var attribute = member[0].GetCustomAttribute<DisplayAttribute>();
        string text = attribute != null ? ((DisplayAttribute)attribute).Name : item.ToString();
        string value = ((int)item).ToString();
        bool selected = item.Equals(metadata.Model);
        return new SelectListItem
        
            Text = text,
            Value = value,
            Selected = selected
        ;
    );
    return html.DropDownListFor(expression, items, string.Empty, null);

【讨论】:

以上是关于在 MVC 4 中将枚举绑定到 DropDownList? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 MVC Razor 在编辑器模板中将 Kendo UI Grid 绑定到我的模型集合

Spring 3.0 MVC 绑定枚举大小写敏感

带有 jQ​​uery Ajax 调用的 MVC 无法正确绑定空数组/可枚举

如何使用C#从asp.net MVC中的枚举绑定下拉列表[重复]

如何在 mvc kendo ui 网格中绑定列的客户端模板中将“this”作为函数参数发送?

在 ASP MVC 4 (Beta) 中将 DateTime 发布到 ApiController