2010-09-14 82 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. 創建相應的資源文件。