ListFor枚举标志MVC.Net

时间:2013-07-24 10:38:13

标签: c# asp.net-mvc razor

我的模型包含一个带有flags属性的枚举

[Flags()]
public enum InvestmentAmount
{
    [Description("£500 - £5,000")]
    ZeroToFiveThousand,

    [Description("£5,000 - £10,000")]
    FiveThousandToTenThousand,

    //Deleted remaining entries for size

}

我希望能够在我的视图中将其显示为多选列表框。 显然,Listfor()的当前帮助程序不支持枚举。

我试过自己滚动但只是接收

  

参数'expression'必须在何时评估为IEnumerable   允许多种选择。

执行时。

public static MvcHtmlString EnumListFor<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);


        RouteValueDictionary htmlattr = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
        //htmlattr.Add("multiple", "multiple");
        if (expression.GetDescription() != null)
        {
            htmlattr.Add("data-content", expression.GetDescription());
            htmlattr.Add("data-original-title", expression.GetTitle());
            htmlattr["class"] = "guidance " + htmlattr["class"];
        }

        var fieldName = htmlHelper.NameFor(expression).ToString();

        return htmlHelper.ListBox(fieldName, items, htmlattr); //Exception thrown here
    }

2 个答案:

答案 0 :(得分:2)

查看我的博客文章,了解我为此创建的帮助方法:

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

这使您可以执行以下操作:

//If you don't have an enum value use the type  
var enumList = EnumHelper.SelectListFor<MyEnum>();  

//If you do have an enum value use the value (the value will be marked as selected)  
var enumList = EnumHelper.SelectListFor(myEnumValue);

...然后您可以使用它来构建多列表。

助手类如下:

public static class EnumHelper  
{  
    //Creates a SelectList for a nullable enum value  
    public static SelectList SelectListFor<T>(T? selected)  
        where T : struct  
    {  
        return selected == null ? SelectListFor<T>()  
                                : SelectListFor(selected.Value);  
    }  

    //Creates a SelectList for an enum type  
    public static SelectList SelectListFor<T>() where T : struct  
    {  
        Type t = typeof (T);  
        if (t.IsEnum)  
        {  
            var values = Enum.GetValues(typeof(T)).Cast<enum>()  
                             .Select(e => new { Id = Convert.ToInt32(e), Name = e.GetDescription() });  

            return new SelectList(values, "Id", "Name");  
        }  
        return null;  
    }  

    //Creates a SelectList for an enum value  
    public static SelectList SelectListFor<T>(T selected) where T : struct   
    {  
        Type t = typeof(T);  
        if (t.IsEnum)  
        {  
            var values = Enum.GetValues(t).Cast<Enum>()  
                             .Select(e => new { Id = Convert.ToInt32(e), Name = e.GetDescription() });  

            return new SelectList(values, "Id", "Name", Convert.ToInt32(selected));  
        }  
        return null;  
    }   

    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)  
    {  
        FieldInfo fi = value.GetType().GetField(value.ToString());  

        if (fi != null)  
        {  
            DescriptionAttribute[] attributes =  
             (DescriptionAttribute[])fi.GetCustomAttributes(  
    typeof(DescriptionAttribute),  
    false);  

            if (attributes.Length > 0)  
            {  
                 return attributes[0].Description;  
            }  
        }  

        return value.ToString();  
    }  
}  

答案 1 :(得分:0)

错误似乎一直在发生,因为我只绑定了一个“InvestmentAmount”,因为看起来ListFor会检查模型是否为列表。

我必须将我的模型更改为List并构建绑定逻辑(通过AutoMapper)以从标记的Enum转换为List并返回。

更好的解决方案是创建一个通用的HTML ListFor帮助程序来完成它。如果我不止一次需要它,我会解决这个问题。