【问题标题】:How do I populate a dropdownlist with enum values?如何使用枚举值填充下拉列表?
【发布时间】:2011-04-11 22:39:51
【问题描述】:

我有一个我的视图模型属性之一的枚举。我想显示一个包含枚举所有值的下拉列表。我可以让它与以下代码一起使用。

我想知道是否有一种简单的方法可以将枚举转换为 IEnumerable?我可以像下面的示例中那样手动执行此操作,但是当我添加新的枚举值时,代码会中断。我想我可以按照example 通过反射来做到这一点,但是还有其他方法可以做到这一点吗?

public enum Currencies
{
  CAD, USD, EUR
}

public ViewModel
{
  [Required]
  public Currencies SelectedCurrency {get; set;}

  public SelectList Currencies
  {
    List<Currencies> c = new List<Currencies>();
    c.Add(Currencies.CAD);
    c.Add(Currencies.USD);
    c.Add(Currencies.EUR);

    return new SelectList(c);
  }
}

【问题讨论】:

    标签: asp.net-mvc generics enums ienumerable


    【解决方案1】:

    也许为时已晚,但我认为它可能对有同样问题的人有用。 我发现 here 现在在 MVC 5 中包含一个 EnumDropDownListFor html 帮助程序,不再需要使用自定义帮助程序或其他解决方法。

    在这种特殊情况下,只需添加以下内容:

        @Html.EnumDropDownListFor(x => x.SelectedCurrency)
    

    仅此而已!

    您还可以通过数据注释和资源文件翻译或更改显示的文本:

    1. 将以下数据注释添加到您的枚举中:

      public enum Currencies
      {
          [Display(Name="Currencies_CAD", ResourceType=typeof(Resources.Enums)]  
          CAD, 
          [Display(Name="Currencies_USD", ResourceType=typeof(Resources.Enums)]    
          USD,
          [Display(Name="Currencies_EUR", ResourceType=typeof(Resources.Enums)]  
          EUR
      }
      
    2. 创建对应的资源文件。

    【讨论】:

      【解决方案2】:

      我正在使用我找到的一个助手 here 来使用通用枚举类型填充我的 SelectLists,不过我做了一些修改以添加选定的值,如下所示:

      public static SelectList ToSelectList<T>(this T enumeration, string selected)
      {
          var source = Enum.GetValues(typeof(T));
      
          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);
      }
      

      它的好处是它将 DisplayAttribute 读取为标题而不是枚举名称。 (如果您的枚举包含空格或您需要本地化,那么它会让您的生活更轻松)

      因此,您需要像这样将 Display attirubete 添加到您的枚举中:

      public enum User_Status
      {
          [Display(Name = "Waiting Activation")]
          Pending,    // User Account Is Pending. Can Login / Can't participate
      
          [Display(Name = "Activated" )]
          Active,                // User Account Is Active. Can Logon
      
          [Display(Name = "Disabled" )]
          Disabled,          // User Account Is Diabled. Can't Login
      }
      

      这就是您在视图中使用它们的方式。

      <%: Html.DropDownList("ChangeStatus" , ListExtensions.ToSelectList(Model.statusType, user.Status))%>
      

      Model.statusType 只是一个User_Status 类型的枚举对象。

      就是这样,您的 ViewModel 中不再有 SelectList。在我的示例中,我在 ViewModel 中引用枚举,但您可以直接在视图中引用枚举类型。我只是为了让一切变得干净和美好。

      希望对您有所帮助。

      【讨论】:

      • 确实很棒的解决方案。但是,如果枚举中的条目没有描述属性,则会失败。因此,将.First() 替换为.FirstOrDefault(),而不是items.Add(value, attrs.GetName()); 替换为items.Add(value, attrs != null ? attrs.GetName() : value.ToString());,这样可以节省您为明显的枚举条目输入说明。
      【解决方案3】:

      我在这方面已经很晚了,但我刚刚找到了一种非常酷的方法,只需一行代码,如果您愿意添加 Unconstrained Melody NuGet 包(Jon Skeet 的一个不错的小型库)。

      这个解决方案更好,因为:

      1. 它确保(使用泛型类型约束)该值确实是一个枚举值(由于 Unconstrained Melody)
      2. 它避免了不必要的拳击(由于不受约束的旋律)
      3. 它缓存所有描述以避免在每次调用时使用反射(由于不受约束的旋律)
      4. 与其他解决方案相比,它的代码更少!

      因此,以下是使其工作的步骤:

      1. 在包管理器控制台中,“Install-Package UnconstrainedMelody”
      2. 像这样在你的模型上添加一个属性:

        //Replace "YourEnum" with the type of your enum
        public IEnumerable<SelectListItem> AllItems
        {
            get
            {
                return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
            }
        }
        

      现在您已经在模型上公开了 SelectListItem 列表,您可以使用 @Html.DropDownList 或 @Html.DropDownListFor 将此属性用作源。

      【讨论】:

        【解决方案4】:

        这么多好的答案 - 我想我应该添加我的解决方案 - 我正在视图中(而不是在控制器中)构建 SelectList:

        在我的 C# 中:

        namespace ControlChart.Models
        //My Enum
        public enum FilterType { 
        [Display(Name = "Reportable")]    
        Reportable = 0,    
        [Display(Name = "Non-Reportable")]    
        NonReportable,    
        [Display(Name = "All")]    
        All };
        
        //My model:
        public class ChartModel {  
        [DisplayName("Filter")]  
        public FilterType Filter { get; set; }
        }
        

        在我的cshtml中:

        @using System.ComponentModel.DataAnnotations
        @using ControlChart.Models
        @model ChartMode
        @*..........*@
        @Html.DropDownListFor(x => x.Filter,                           
        from v in (ControlChart.Models.FilterType[])(Enum.GetValues(typeof(ControlChart.Models.FilterType)))
        select new SelectListItem() {
            Text = ((DisplayAttribute)(typeof(FilterType).GetField(v.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false).First())).Name,                             
            Value = v.ToString(),                             
            Selected = v == Model.Filter                           
            })
        

        HTH

        【讨论】:

          【解决方案5】:

          查看 Enum.GetNames(typeof(Currencies))

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多