Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Html 在MVC4中将枚举绑定到DropDownList?_Html_Asp.net Mvc_Data Binding_Drop Down Menu_Enums - Fatal编程技术网

Html 在MVC4中将枚举绑定到DropDownList?

Html 在MVC4中将枚举绑定到DropDownList?,html,asp.net-mvc,data-binding,drop-down-menu,enums,Html,Asp.net Mvc,Data Binding,Drop Down Menu,Enums,我在各地都发现,将枚举绑定到下拉列表的常用方法是通过helper方法,这对于这样一个看似简单的任务来说似乎有点霸道 在ASP.Net MVC 4中,将枚举绑定到DropDownList的最佳方法是什么?我认为这是唯一(干净的)方法,这很遗憾,但至少有一些选择。我建议大家看看这个博客: 抱歉,这里的复制太长,但要点是他为此创建了一个新的HTML助手方法 所有的源代码都可以在上找到。来自PaulTheCyclist的解决方案就在这里。但我不会使用RESX(我必须为每个新枚举添加一个新的.RESX文件

我在各地都发现,将枚举绑定到下拉列表的常用方法是通过helper方法,这对于这样一个看似简单的任务来说似乎有点霸道


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

我认为这是唯一(干净的)方法,这很遗憾,但至少有一些选择。我建议大家看看这个博客:

抱歉,这里的复制太长,但要点是他为此创建了一个新的HTML助手方法


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

来自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);
}
以下是Razor视图的调用:

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

从技术上讲,您不需要助手方法,因为
Html.DropdownListFor
只需要
SelectList
Ienumerable
。您只需将枚举转换为这样的输出,并以这种方式提供数据

我使用静态库方法将枚举转换为
列表
,并带有几个参数/选项:

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;
}
公共静态列表GetEnumsByType(bool useFriendlyName=false,列表排除=null, 列出eachSelected=null,bool useIntValue=true),其中T:struct,IConvertible { var enumList=来自EnumUtil.GetEnumValuesFor()中的enumItem 其中(exclude==null | |!exclude.Contains(enumItem)) 选择枚举项; var list=新列表(); foreach(枚举列表中的变量项) { var selItem=new SelectListItem(); selItem.Text=(useFriendlyName)?item.ToFriendlyString():item.ToString(); selItem.Value=(useIntValue)?item.To().ToString():item.ToString(); if(eachSelected!=null&&eachSelected.Contains(项)) selItem.Selected=true; 列表。添加(选择项); } 退货清单; } 公共静态类EnumUtil { 用于()的公共静态IEnumerable GetEnumValuesFor { 返回Enum.GetValues(typeof(T)).Cast(); } //这里还有其他东西。。。 } /// ///将大小写或下划线分隔的短语转换为正确的空格短语 ///“带芥末的狗”。ToFriendlyString()=“带芥末的狗” /// 公共静态字符串ToFriendlyString(此对象为o) { var s=o.ToString(); s=s.Replace(“uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu; char[]origArray=s.ToCharArray(); List newCharList=新列表(); for(int i=0;i 您的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); 
    }
}
public IEnumerable PaymentMethodChoices
{ 
得到
{ 
var Exclutions=新列表{Membership.Payment.PaymentMethod.Unknown,Membership.PaymentMethod.Reversion};
var selected=新列表{this.SelectedPaymentMethod};
返回GetEnumsByType(useFriendlyName:true,exclude:Excludes,eachSelected:selected);
}
}
因此,您将视图的
DropDownList
与我的控制器中的
IEnumerable
属性关联起来。

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.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))

从MVC 5.1开始,框架就支持枚举:

@Html.EnumDropDownListFor(m => m.Palette)
可以自定义显示的文本:

public enum Palette
{
    [Display(Name = "Black & White")]
    BlackAndWhite,

    Colour
}

MSDN link:

扩展html帮助程序可以很好地完成这项工作,但是如果您希望能够基于DisplayAttribute映射更改下拉值的文本,则需要对其进行类似的修改

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

公共静态IHtmlString EnumDropDownListFor(此HtmlHelper html,表达式)
{
var metadata=modelmetada.FromLambdaExpression(表达式,html.ViewData);
var enumType=Nullable.GetUnderlinegType(metadata.ModelType)??metadata.ModelType;
var enumValues=Enum.GetValues(enumType.Cast();
变量项=枚举值。选择(项=>
{
var type=item.GetType();
var member=type.GetMember(item.ToString());
var attribute=成员[0]。GetCustomAttribute();
字符串文本=属性!=null?((DisplayAttribute)属性)。名称:item.ToString();
字符串值=((int)项).ToString();
bool selected=item.Equals(metadata.Model);
返回新的SelectListItem
{
Text=Text,
值=值,
选定的=选定的
};
});
返回html.DropDownListFor(表达式、项、字符串.Empty、null);
}

这个问题回答了这个答案的要点:以及这个问题的许多其他解决方案。保尔自行车手的建议很好,但他在那篇文章中遗漏了很多细节。。。最好直接去他的github。谢谢,如果有人感兴趣(我知道OP指定了MVC4),MVC5.1有enum支持:这里有更好的解决方案。正如Bernard所说,如果您能够使用该版本,MVC5.1现在就涵盖了这一点。我在上一篇博客的基础上写了一篇新的博客文章,展示了一种方法,你可以利用它,并且仍然可以从resx文件中获取下拉值。嗨,如果你要使用基于我博客的解决方案,你只需要一个resx文件就可以获得所有枚举,并且只需要使用约定来区分枚举。e、 如果你有两个枚举,颜色和数字表示。一些resx条目可能有如下名称:color\u Blue、color\u Red、color\u White、LoanApplicationType\u Undefined、LoanApplicationType\u Personal。描述属性工作得很好,但是如果你的Web应用不需要考虑本地化,我猜如果你需要本地化多种语言,这是有意义的。当我不得不使用RESX文件时,我通常使用自定义DataAnnotationAttribute对枚举进行装饰,并直接在枚举上设置资源文件条目。但是
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))
@Html.EnumDropDownListFor(m => m.Palette)
public enum Palette
{
    [Display(Name = "Black & White")]
    BlackAndWhite,

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