2010-02-21 54 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

相关问题