2010-02-21 64 views
1

這所返回到視圖類有來自其他表的幾個枚舉值:我想有一個選擇框如何啓用值的下拉列表編輯在MVC視圖

class Person{ 
int id; 
enum Rank; 
enum Status; 
} 

在「編輯」觀與選定的值 ,以便用戶能夠更改爲另一個枚舉值。

我得到的枚舉值成的ViewData:

<%= Html.DropDownList("Rank")%> 

你怎麼能選擇從模型中的價值? 像這樣:

<%= Html.DropDownList("Rank", item.Rank)%> 

而且一旦改變如何保存更改?

回答

0

我認爲你正在尋找Enum.Parse:

Rank rankValue = (Rank) Enum.Parse(typeof(Rank), rankString);  
2

我發現自己想對枚舉足夠頻繁,我創造了一些方便的擴展方法做的下拉列表。他們允許我通過以下方式創建下拉列表:

它使用FooFor的HtmlHelper擴展方法模式做的強類型下拉創作:

<%= Html.EnumDropdownFor(model => model.MyProperty) %> 

這裏有一些,強類型較少的版本:

<%= Html.EnumDropdown("MyProperty", MyEnum.AValue /* selected value */) %> 

<%= Html.EnumDropdown(
     "MyProperty", 
     new MyEnum[] { MyEnum.AValue, MyEnum.BValue } /* choices */) %> 

<%= Html.EnumDropdown(
     "MyProperty", 
     MyEnum.AValue         /* selected value */, 
     new MyEnum[] { MyEnum.AValue, MyEnum.BValue } /* choices  */) %> 

在我的實現中,如果默認ToString結果不可接受,我還創建了一個名爲EnumDisplayNameAttribute的自定義屬性,將漂亮的名稱分配給枚舉值。這裏的擴展方法和輔助類我寫來支持這一切:

public class EnumDisplayNameAttribute : Attribute 
{ 
    public EnumDisplayNameAttribute(string name) 
    { 
     this.DisplayName = name; 
    } 

    public string DisplayName { get; private set; } 
} 

public static class EnumUtils 
{ 
    private static Dictionary<Type, IDictionary<object, string>> _nameLookups = 
     new Dictionary<Type, IDictionary<object, string>>(); 

    public static string GetDisplayName<T>(this T value) 
    { 
     var type = typeof(T); 
     if (!_nameLookups.ContainsKey(type)) 
     { 
      _nameLookups[typeof(T)] = GetEnumFields<T>() 
       .ToDictionary(
        f => f.GetValue(null), 
        f => f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), true) 
          .OfType<EnumDisplayNameAttribute>() 
          .Select(a => a.DisplayName) 
          .FirstOrDefault() 
         ?? f.Name); 
     } 
     return _nameLookups[type][value]; 
    } 

    public static IEnumerable<FieldInfo> GetEnumFields<T>() 
    { 
     return typeof(T) 
      .GetFields(BindingFlags.Public | BindingFlags.Static) 
      .OfType<FieldInfo>(); 
    } 

    public static IEnumerable<T> GetEnumValues<T>() 
    { 
     return Enum.GetValues(typeof(T)).Cast<T>(); 
    } 
} 

public static class HtmlHelperExtensions 
{ 
    public static MvcHtmlString EnumDropdownFor<TModel, TValue>(
     this HtmlHelper<TModel> helper, 
     Expression<Func<TModel, TValue>> expression) 
    { 
     var data = expression.Compile()(helper.ViewData.Model); 
     StringBuilder builder = new StringBuilder(); 
     builder.AppendFormat(
      "<select name='{0}' id='{0}'>", 
      helper.Encode(
       (expression.Body as MemberExpression).Member.Name)); 
     EnumUtils.GetEnumFields<TValue>() 
      .ForEach(f => { 
       var nameAttrib = f 
        .GetCustomAttributes(
         typeof(EnumDisplayNameAttribute), true) 
        .OfType<EnumDisplayNameAttribute>().FirstOrDefault(); 
       var displayName = (nameAttrib == null) 
        ? f.Name : nameAttrib.DisplayName; 

       var optionData = (TValue)f.GetRawConstantValue(); 
       builder.AppendFormat(
        "<option value=\"{0}\" {1}>{2}</option>", 
        optionData, 
        optionData.Equals(data) ? "selected=\"selected\"" : "", 
        displayName); 
      } 
     ); 
     builder.Append("</select>"); 
     return MvcHtmlString.Create(builder.ToString()); 
    } 

    public static MvcHtmlString EnumDropdown<TModel, TValue>(
     this HtmlHelper<TModel> helper, string name, TValue value) 
    { 
     return helper.EnumDropdown(
      name, value, EnumUtils.GetEnumValues<TValue>()); 
    } 

    public static MvcHtmlString EnumDropdown<TModel, TValue>(
     this HtmlHelper<TModel> helper, string name, 
     IEnumerable<TValue> choices) 
    { 
     return helper.EnumDropdown(name, choices.FirstOrDefault(), choices); 
    } 

    public static MvcHtmlString EnumDropdown<TModel, TValue>(
     this HtmlHelper<TModel> helper, string name, TValue value, 
     IEnumerable<TValue> choices) 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.AppendFormat("<select name='{0}'>", helper.Encode(name)); 
     if (choices != null) 
     { 
      choices.ForEach(
       c => builder.AppendFormat(
        "<option value=\"{0}\"{2}>{1}</option>", 
        Convert.ToInt32(c), 
        helper.Encode(EnumUtils.GetDisplayName(c)), 
        value.Equals(c) ? " selected='selected'" : "")); 
     } 
     builder.Append("</select>"); 
     return MvcHtmlString.Create(builder.ToString()); 
    } 
} 

編輯:

我忘了,包括擴展方法,增加了的ForEach到IEnumerable

public static class CollectionUtils 
{ 
    public static void ForEach<T>(
     this IEnumerable<T> collection, Action<T> action) 
    { 
     foreach (var item in collection) 
     { 
      action(item); 
     } 
    } 
} 
+0

< %= Html.EnumDropdownFor(model => model.MyProperty)%>非常棒! 非常感謝你的雅各布。 我還需要完成對某些領域的研究才能理解它。 我想知道他們爲什麼沒有完成所有'Form'元素。這很酷。 – safhac 2010-02-21 20:32:24

+0

嗨, 我忘了提及我使用框架4.0,不支持泛型類型的.Foreach操作。 你會如何取代? – safhac 2010-02-22 08:06:54

+0

另一種擴展方法。我會將其添加到我的答案的底部。 – Jacob 2010-02-22 16:10:23