如何在填充了枚举值的DropDownList中选择多个值?

时间:2014-08-07 09:34:04

标签: asp.net-mvc asp.net-mvc-3 enums multi-select html.dropdownlistfor

我正在使用ASP.NET MVC3,我想用枚举值填充DropDownList并选择一个或多个选项。

我自定义了DropDownList,看起来像是一个“CheckedDropDownList”,并且,在一个非常基本的Edit形式中,我需要检查实际值。

以下是我的Enum的构建方式:

public enum MyEnum
{
    [Display(Name = "Undefined")]
    UNDEFINED = -1, //I really need this "detail"

    [Display(Name = "First Value")]
    VALUE1,

    [Display(Name = "Second Value")]
    VALUE2

    [Display(Name = "Other")]
    OTHER,
}

我也在使用这个ToLocalizedSelectList<>()方法,我尝试从this SO question进行调整,但我无法修改它以接受多个选定的值。

public static SelectList ToLocalizedSelectList<T>(this T enumeration, string selected)
{
    var source = Enum.GetValues(typeof(T)).Cast<T>().OrderBy(x => x); //I always need UNDEFINED as first element
    var items = new Dictionary<object, string>();
    var displayAttributeType = typeof(DisplayAttribute);

    foreach (var value in source)
    {
        FieldInfo field = value.GetType().GetField(value.ToString());
        DisplayAttribute attrs = (DisplayAttribute)field.GetCustomAttributes(displayAttributeType, false).FirstOrDefault();
        items.Add(value, attrs != null ? attrs.GetName() : value.ToString());
    }

    return new SelectList(items, "Key", "Value", selected);
}

以下是我如何使用它:

@Html.DropDownListFor(m => m.EnumValues, 
                      AttributesHelperExtension.ToLocalizedSelectList<MyEnum>(MyEnum.UNDEFINED, Enum.GetName(typeof(MyEnum), Model.EnumValues.First())
                      Enum.GetName(typeof(MyEnum), Model.EnumValues.First())),
                      new { @id = "ddlEnumValue" }
                     )

EnumValues定义为:

public MyEnum[] EnumValues { get; set; }

我认为问题在于第三个参数,我需要传递Model.EnumValues而不是Model.EnumValues.First(),它总是只选择我{{{}的第一个项目1}}枚举。

第二个参数也可能是个问题,因为MyEnum需要此MyEnum枚举作为第一个参数,所以我将第一个参数传递给它我的枚举,但我不确定这是一个很好的解决方案。

我如何转换此ToLocalizedSelectList<>()方法,以便接受多个选定的值,以及如何在ToLocalizedSelectList<>()(或@Html.DropDownListFor)中使用它?

非常感谢


仅供参考,我也试过这段代码:

@Html.ListBoxFor

并预先选择好的 valueS ,然而,它会显示枚举名称,例如@Html.ListBoxFor(m => m.EnumValues, new SelectList(Enum.GetValues(typeof(MyEnum)) .Cast<MyEnum>() .OrderBy(e => (int)e) ), new { @id = "ddlMyEnum" } ) UNDEFINED,而不是VALUE1属性({{ 1}},Display Name)等...

2 个答案:

答案 0 :(得分:1)

注意:这只解决了代码中的部分问题 - 显示“友好”的问题。枚举说明。

创建扩展方法以获取友好描述。请注意,这使用[Description]属性而不是[Display]属性

public static string ToDescription(this Enum value)
{
  FieldInfo field = value.GetType().GetField(value.ToString());
  DescriptionAttribute[] attributes = (DescriptionAttribute[])field
    .GetCustomAttributes(typeof(DescriptionAttribute), false);
  if (attributes.Length > 0)
  {
    return attributes[0].Description;
  }
  return value.ToString();
}

可与

一起使用
public enum ProjectStatus
{
  Draft,
  [Description("In limbo")]
  OnHold,
  Completed
}

然后创建一个扩展方法来创建一个选择列表

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.ToDescription() }; // or ID = (int)e, depending on what you want the as the value
  return new SelectList(values, "ID", "Name", enumObj);
}

并像这样使用它,你的模型有属性public ProjectStatus status { get; set; }

@Html.DropDownListFor(m => m.Status, Model.Status.ToSelectList())

至于其他方面,我不了解你的方法,以及如何创建一个枚举值数组将有任何好处或如何将结果存储在数据库中。我的方法是在视图模型中创建布尔属性,然后让用户检查他们想要的选项。

答案 1 :(得分:0)

我刚刚使用以下方法纠正了这个旧版本的错误:

@Html.ListBoxFor(m => m.EnumValues, 
                 Model.EnumValues.ToLocalizedSelectList<MyEnum>(Model.EnumValues.ToList())
                )

ToLocalizedSelectList<>()与上面发布的相同,但签名除外:

public static SelectList ToLocalizedSelectList<T>(this T[] enumeration, List<T> selected)

希望它有助于某人