简体   繁体   English

将枚举值传递到ASP.NET MVC3中的ListBoxFor

[英]Passing enum values to a ListBoxFor in ASP.NET MVC3

I've read up a good bit on creating a SelectList from an Enum to populate a drop down list, and found many solutions. 我已经阅读了很多有关从Enum创建SelectList来填充下拉列表的知识,并找到了许多解决方案。 Here are a few examples 这里有一些例子

public static IEnumerable<SelectListItem> GetEnumSelectList<T>()
{
    return (Enum.GetValues(typeof(T)).Cast<T>().Select(
        enu => new SelectListItem() { Text = enu.ToString(), Value = enu.ToString() })).ToList();
}

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) 
    where TEnum : struct, IComparable, IFormattable, IConvertible
{
    var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                 select new { Id = e, Name = e.ToString() };
    return new SelectList(values, "Id", "Name", enumObj);
}

Both of these (and most others) return the names of the enum values for both Text and Value . 这两个(以及大多数其他)都返回TextValue的枚举值的名称。

Example

public enum WeatherInIreland
{
     NotGreat = 0,
     Bad = 1,
     Awful = 2
} 

Results from the first two methods 前两种方法的结果

<select id="Weather" name="Weather">
    <option value="NotGreat">NotGreat</option>
    <option value="Bad">Bad</option>
    <option value="Awful">Awful</option>
</select>

However, I wanted to return the name for Text and the int value for the Value . 但是,我想返回Text名称Valueint值

<select id="Weather" name="Weather">
    <option value="0">NotGreat</option>
    <option value="1">Bad</option>
    <option value="2">Awful</option>
</select>

This is the code I came up with. 这是我想出的代码。

public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct, IComparable, IFormattable, IConvertible
{
    List<SelectListItem> selist = new List<SelectListItem>();
    foreach (int value in Enum.GetValues(typeof(TEnum)))
    {
        TEnum type = (TEnum)Enum.Parse(typeof(TEnum), value.ToString());
        selist.Add(new SelectListItem { Value = value.ToString(), Text = type.ToString() });
    }
    return new System.Web.Mvc.SelectList(selist, "Value", "Text");
}

As you can see it's a modified version of the last method above. 如您所见,它是上面最后一个方法的修改版本。 It works, but it is ugly. 它可以工作,但是很难看。 I have to iterate over the Enum values as ints and then separately parse each one to return the name. 我必须将Enum值迭代为整数,然后分别解析每个数字以返回名称。 Surely there's a better way of doing this? 当然有更好的方法吗?

You have to write it this way: 您必须这样写:

public static System.Web.Mvc.SelectList ToSelectList<T>(this Enum TEnum) where T : struct, IComparable, IFormattable, IConvertible
{

    return new SelectList( Enum.GetValues(typeof(T)).OfType<T>()
                                                .Select(x =>
                                                   new SelectListItem
                                                   {
                                                       Text = x.ToString(),
                                                       Value = ((T)x).ToString()
                                                   }));
}

REVISED ONE: 修订一:

public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj) where TEnum : struct, IComparable, IFormattable, IConvertible
{

  return new SelectList(Enum.GetValues(typeof(TEnum))
                                      .OfType<Enum>()
                                      .Select(x =>
                                      new SelectListItem
                                         {
                                          Value = (Convert.ToInt32(x)).ToString(),
                                          Text = Enum.GetName(typeof(TEnum),x)
                                         }
                                         ),"Value","Text");

}

I tested it on my machine and it works fine. 我在机器上对其进行了测试,并且工作正常。

Unfortunately there's not really a better way to do this. 不幸的是,没有真正更好的方法来做到这一点。 In a perfect world, Enum would implement IEnumerable and you could iterate through the collection. 在理想情况下, Enum将实现IEnumerable ,您可以遍历集合。 Instead you can only either iterate through Enum.GetValues or Enum.GetNames . 相反,您只能通过Enum.GetValuesEnum.GetNames进行迭代。 Whichever you choose, you'll still need to call Enum.GetName or Enum.GetValue to get the other piece of data. 无论您选择哪种方式,都仍然需要调用Enum.GetNameEnum.GetValue来获取其他数据。

Similiar StackOverflow question: C# Iterating through an enum? 类似的StackOverflow问题: C#遍历枚举? (Indexing a System.Array) (索引System.Array)

You can however make the code a bit more readable and linq-y : 但是,您可以使代码更具可读性和linq-y

 return
      new SelectList(
          Enum.GetValues(typeof (TEnum))
              .Select(e => new SelectListItem
              {
                 Text = Enum.GetName(typeof (TEnum), e),
                 Value = e.ToString()
              })
              .ToList(),
          "Value",
          "Text");

We made a helper at work which does this really well 我们在工作中做了一个很好的助手

public static class EnumDescriptionDropDownList
{
    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 EnumDescriptionDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDescriptionDropDownListFor(htmlHelper, expression, null);
    }

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

Then you simply call it on your view for the enum in the Model or ViewModel (whichever your using) 然后,您只需在视图中为Model或ViewModel中的枚举调用它(无论使用哪种方式)

@Html.EnumDescriptionDropDownListFor(model => model.Type)    

Also if you put a Description attribute on each enum option you also get a nice user friendly string, if not then it just uses the regular string value of the enum. 另外,如果在每个枚举选项上放置一个Description属性,您还将获得一个友好的用户友好字符串,如果没有,则它仅使用枚举的常规字符串值。

[Description("MOT Checker")]    

Finally if you change the value in the select list to the following it will output the int value instead of the string also (which is what what you want i believe?); 最后,如果将选择列表中的值更改为以下值,它将输出int值而不是字符串(这是我想要的吗?);

Value = Convert.ToInt32(value).ToString(),

<option value="1">e1</option>
<option value="2">e2</option>
<option value="3">e3</option>
<option value="4">e4</option>
<option value="5">e5</option>
<option value="6">e6</option>

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM