【问题标题】:How do I select multiple values in a DropDownList populated with enum values?如何在填充了枚举值的 DropDownList 中选择多个值?
【发布时间】:2014-09-30 11:43:50
【问题描述】:

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

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

这是我的枚举的构造方式:

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(),它总是只预选我的MyEnum 枚举的第一项。

第二个参数也可能是个问题,因为ToLocalizedSelectList&lt;&gt;()需要一个this MyEnum枚举作为第一个参数,所以我将它作为我的枚举的第一项传递,但我不确定这是一个好的解决方案。

如何转换此ToLocalizedSelectList&lt;&gt;() 方法以使其接受多个选定值,以及如何在@Html.DropDownListFor(或@Html.ListBoxFor)中使用它?

非常感谢


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

@Html.ListBoxFor(m => m.EnumValues, 
                  new SelectList(Enum.GetValues(typeof(MyEnum))
                     .Cast<MyEnum>()
                     .OrderBy(e => (int)e)
                  ), new { @id = "ddlMyEnum" }
                 )

它预先选择了好的valueS,但是,它显示枚举名称,例如UNDEFINEDVALUE1,而不是它们的Display Name属性(UndefinedFirst Value)等等……

【问题讨论】:

  • 是否有理由不去寻找已经存在的东西,例如harvesthq.github.io/chosen???
  • 我没有在插件中看到您链接了如何将简单的 DropDownList 转换为 CheckedDropDownList,每个选项前面都有 Checkbox,所以我认为这是一个不使用它的好理由。老实说,我使用 jQuery 多选插件来执行此操作:erichynds.com/blog/jquery-ui-multiselect-widget。 99% 的工作已经完成,我只想回答下面的问题,以获取缺失的 1% 并关闭此问题。
  • 还不错,很好奇。
  • 我在这里看到了很多问题。首先,如果要选择多个值,则需要 @Html.ListBoxFor(),而不是 @HtmlDropDownListFor()ToLocalizedSelectList() 的第一个参数是枚举类型,但您传递的是枚举值。第二个参数似乎毫无意义,因为 @Html.ListBoxFor() 方法将根据 yot 属性 EnumValues 中的值将值标记为选中。然后是为此使用枚举的逻辑。也许您应该使用 [Flags] 属性,这样您就可以将枚举值(标志)集合分配给属性,而不是枚举值数组
  • @StephenMuecke,我尝试将第一个参数更改为typeof(MyEnum),或MyEnum,但没有成功。你能提供一个代码示例吗? [Flags]属性我不熟悉,我去看看。

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


【解决方案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())

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

【讨论】:

  • 您的代码正在运行,所以我赞成;但是,正如您自己所说的那样,它并不能真正解决问题,因为我已经知道如何在 DropDownListFor 中显示 [Display] 属性(请参阅我的第一篇文章的最后一部分)。我真正需要的是如何在ListBoxFor 中预先选择由Display 属性显示的多个元素
  • 谢谢(没想到会打勾)。这可能会奏效。如果EnumValuesint[] 并且它的值被设置为[1, 3] 并且SelectList 将选项值创建为int(在我的扩展方法中它将是select new { ID = (int)e, Name = e.ToDescription() } 然后@Html.ListBoxFor(m =&gt; m.EnumValues, Model.X) 应该(也许)选择第二个和第四个值。注意Model.X 是您的视图模型public MyEnum Something { get; set; } 中的一个属性,默认为UNDEFINED,因此您可以生成具有友好名称的选择列表,并在EnumValues 为空时提供默认选择跨度>
【解决方案2】:

我今天刚刚纠正了这个旧错误:

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

其中ToLocalizedSelectList&lt;&gt;()与上面发布的相同,除了签名:

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

希望对某人有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多