2010-09-14 81 views
8

我有一个枚举为我的视图模型的属性之一。我想显示一个包含枚举值的下拉列表。我可以通过下面的代码来解决这个问题。如何使用枚举值填充下拉列表?

我想知道的是,是否有一个简单的方法从枚举转换为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); 
    } 
} 

回答

18

我使用了一个帮手,我发现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作为标题,而不是枚举名。 (如果你的枚举包含空格或者你需要本地化,然后它会让你的生活变得更轻松)

所以,你需要将显示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类型的枚举对象。

就是这样,ViewModels中没有更多的SelectLists。在我的示例中,我正在折叠ViewModel中的枚举,但您可以直接在您的视图中引用枚举类型。我只是为了让一切变得干净而美好。

希望有帮助。

+0

伟大的解决方案! – 2012-01-30 00:28:34

+3

确实很棒。但是,如果enum中的条目没有description属性,则失败。所以用'.FirstOrDefault()'替换'.First()'而不是'items.Add(value,attrs.GetName());''有'items.Add(value,attrs!= null?attrs.GetName ):value.ToString());''''''''''''''''''''''''''' – trailmax 2012-08-13 13:30:19

+0

完成,感谢您的更正。 – 2014-07-04 12:42:10

2

看Enum.GetNames(typeof运算(货币))

1

因此,许多很好的答案 - 我想I'sd添加我的解决方案 - 我建立在视图中选择列表的(而不是在Controller):

在我的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

1

我就这一个非常晚,但我刚刚发现了一个非常酷娃如果您愿意添加Unconstrained Melody NuGet包(Jon Skeet的一个不错的小型图书馆),则可以使用一行代码执行此操作。

这种溶液更好,因为:

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

因此,这里有得到这个工作的步骤:

  1. 在包管理器控制台中,“安装,包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使用此属性作为源。

0

也许为时已晚,但我认为它可能对有同样问题的人有用。 我发现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. 创建相应的资源文件。