2010-08-07 72 views
19

如何爲枚舉創建默認編輯器模板?我的意思是:我可以做這樣的事情:如何爲枚舉創建默認編輯器模板?

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %> 
<% -- any code to read the enum and write a dropdown --> 

,並把這個在EditorTemplates文件夾名稱Enum.ascx下?

下面是我嘗試過的問題的解決方法,但這不是我所需要的。

這裏是我的枚舉:

public enum GenderEnum 
{ 
    /// <summary> 
    /// Male 
    /// </summary> 
    [Description("Male Person")] 
    Male, 

    /// <summary> 
    /// Female 
    /// </summary> 
    [Description("Female Person")] 
    Female 
} 

我做一個GenderEnum.acsx模板,並把它放在Shared/EditorTemplates文件夾中。這裏是模板:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AlefTech.HumanResource.Core.GenderEnum>" %> 
<%@ Import Namespace="AlefTech.HumanResource.WebModule.Classes" %> 
<%=Html.DropDownListFor(m => m.GetType().Name, Model.GetType()) %> 

當然的方法是我自己:

public static class HtmlHelperExtension 
    { 
     public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType) 
     { 
      List<SelectListItem> list = new List<SelectListItem>(); 
      Dictionary<string, string> enumItems = enumType.GetDescription(); 
      foreach (KeyValuePair<string, string> pair in enumItems) 
       list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value }); 
      return htmlHelper.DropDownListFor(expression, list); 
     } 

     /// <summary> 
     /// return the items of enum paired with its descrtioption. 
     /// </summary> 
     /// <param name="enumeration">enumeration type to be processed.</param> 
     /// <returns></returns> 
     public static Dictionary<string, string> GetDescription(this Type enumeration) 
     { 
      if (!enumeration.IsEnum) 
      { 
       throw new ArgumentException("passed type must be of Enum type", "enumerationValue"); 
      } 

      Dictionary<string, string> descriptions = new Dictionary<string, string>(); 
      var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field); 

      foreach (MemberInfo member in members) 
      { 
       var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), false); 
       if (attrs.Count() != 0) 
        descriptions.Add(member.Name, ((DescriptionAttribute)attrs[0]).Description); 
      } 
      return descriptions; 
     } 

    } 

然而,即使這個工作對我來說,這不是我在問什麼。相反,我需要以下工作:

代碼Shared\EditorTemplates\Enum.acsx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %> 
<%@ Import Namespace="System.Web.Mvc.Html" %> 
<%@ Import Namespace="WhereMyExtentionMethod" %> 
<%=Html.DropDownListFor(m => m.GetType().Name, Model.GetType()) %> 

有了這個,我就不用做每一個枚舉任何更多的模板。

+0

你還沒有得到這個工作? 你介意發佈這裏使用的助手代碼:return htmlHelper.DropDownListFor(expression,list);? – 2010-08-09 18:15:12

+0

順便說一句,如果您在模型的enum字段中放置了[UIHint(「Enum」)],則代碼應該可以工作,請將類型System.Web.Mvc.ViewUserControl 更改爲動態,然後將它們轉換爲正確的類型在幫手電話:) – 2010-08-09 18:30:58

回答

7

之前,感謝大家的貢獻
Yngvebn,我想你的解決方案(在你最後的評論),但我沒有做的唯一的事情是<dynamic>,我代替<Enum>在泛型類型。

最後的解決方案是:
創建一個名爲Enum.acsx模板,並把它下視圖\共享\ EditorTemplates

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %> 
<%@ Import Namespace="System.Web.Mvc.Html" %> 
<%@ Import Namespace="the extension methods namespace" %> 
<% Enum model = (Enum)Model; %> 
<%=Html.DropDownList(model.GetType().Name,model.GetType())%> 

,並在你的實體:

public class Person 
{ 
    [UIHint("Enum")] 
    public GenderEnum Gender{get;set;} 
} 

public Enum GenderEnum 
{ 
[Description("Male Person")] 
Male, 
[Description("Female Person")] 
Female 
} 

並且再次有延伸方法:

public static class HtmlHelperExtension 
    { 
     public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType) 
     { 
      List<SelectListItem> list = new List<SelectListItem>(); 
      Dictionary<string, string> enumItems = enumType.GetDescription(); 
      foreach (KeyValuePair<string, string> pair in enumItems) 
       list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value }); 
      return htmlHelper.DropDownListFor(expression, list); 
     } 

     /// <summary> 
     /// return the items of enum paired with its descrtioption. 
     /// </summary> 
     /// <param name="enumeration">enumeration type to be processed.</param> 
     /// <returns></returns> 
     public static Dictionary<string, string> GetDescription(this Type enumeration) 
     { 
      if (!enumeration.IsEnum) 
      { 
       throw new ArgumentException("passed type must be of Enum type", "enumerationValue"); 
      } 

      Dictionary<string, string> descriptions = new Dictionary<string, string>(); 
      var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field); 

      foreach (MemberInfo member in members) 
      { 
       var attrs = member.GetCustomAttributes(typeof(DescriptionAttribute), false); 
       if (attrs.Count() != 0) 
        descriptions.Add(member.Name, ((DescriptionAttribute)attrs[0]).Description); 
      } 
      return descriptions; 
     } 

    } 
+1

您是否真的嘗試過這種解決方案?有編譯時錯誤 – 2010-11-15 07:22:25

+0

當然,Vince我試過了,你是什麼樣的編譯錯誤? ......如果你願意,可以在這裏發佈,也許我可以幫助你。 – 2010-11-15 19:00:11

+0

我在看這個,你好像爲DropDownFor添加了代碼,並給出了使用DropDown的例子,這就是問題所在。我當時也被扔掉了。 – efbenson 2012-09-26 19:35:27

0

幾乎可以確定這是開箱即用的。


嘗試將您的模板命名爲與枚舉相同的名稱。

+0

其實我做到了,但它沒有工作。 我做了這個文件,但是文件永遠不會被調用。 我認爲proplem是(Enum)不是一種類型? – 2010-08-07 18:36:18

+0

好吧,我想要做的是在我的解決方案中爲所有聲明的Enum創建一個文件。 就像我爲(int) 創建了一個默認編輯器模板,所以每當有(int)的屬性時,mvc將使用該模板。 您建議的解決方案讓我爲我的項目中的每種枚舉創建一個模板。 – 2010-08-07 19:15:11

1

我不認爲有一種默認的方式來定義所有枚舉類型的編輯器,因爲你可能需要不同的行爲取決於情況。例如,也許你有一個[Flags]枚舉並希望多選,或者你想要一個下拉列表,或者你想要單選按鈕。

另外,通常你會想要一些有意義的顯示字符串,超出了你在變量命名限制中可以完成的內容。

當然分配給一個enum類型的屬性可以開箱即用,但是如何獲得該值將取決於您。

5

這裏有一個幫手我這個做.. 在你看來,你可以簡單地做:

<%= Html.DropDownForEnum<MyEnum>("some-name-for-dropdown", MyEnum.TheFirstValue) %> 

在實際的下拉列表中的文本,將尋找在資源文件相匹配的資源枚舉的名稱,否則只需編寫實際的Enumtext本身。

public static MvcHtmlString DropDownForEnum<T>(this HtmlHelper h, string name, T selectedValue) 
{ 
    Type enumType = typeof(T); 
    Tag t = new Tag("select").With("name", name).And("id", name); 

    foreach (T val in Enum.GetValues(enumType)) 
    { 
     string enumText = Resources.ResourceManager.GetString(val.ToString()); 
     if (String.IsNullOrEmpty(enumText)) enumText = val.ToString(); 
     Tag option = new Tag("option").With("value", (val).ToString()).AndIf(val.Equals(selectedValue), "selected", "selected").WithText(enumText); 
     t.Append(option); 
    } 
    return MvcHtmlString.Create(t.ToString()); 
} 

如果您希望它不需要重寫,您還需要重載的標記類。

public class Tag : TagBuilder 
{ 
public Tag (string TagName): base(TagName) 
{ 

} 

public Tag Append(Tag innerTag) 
{ 
    base.InnerHtml += innerTag.ToString(); 
    return this; 
} 

public Tag WithText(string text) 
{ 

    base.InnerHtml += text; 
    return this; 
} 

public Tag With(Tag innerTag) 
{ 
    base.InnerHtml = innerTag.ToString(); 
    return this; 
} 

public Tag With(string attributeName, string attributeValue) 
{ 
    base.Attributes.Add(attributeName, attributeValue); 
    return this; 
} 

public Tag And(string attributeName, string attributeValue) 
{ 
    base.Attributes.Add(attributeName, attributeValue); 
    return this; 
} 


public Tag AndIf(bool condition, string attributeName, string attributeValue) 
{ 
    if(condition) 
     base.Attributes.Add(attributeName, attributeValue); 
    return this; 
} 
} 
+0

這是偉大的Yngvebn, 但它仍然不能回答我的問題。 實際上,爲了解決我的問題,我做了類似於您的代碼的東西,但是我沒有使用這些資源,而是在Enum的每個元素上使用了Description屬性。 我將添加一個包含我的代碼的答案。 – 2010-08-09 16:09:16

5

Nour Sabony,我修改了您的版本以支持本地化與資源。因此,我改變了DescriptionAttribute到DisplayAttribute的DataAnnotations命名空間

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType) 
    { 
     List<SelectListItem> list = new List<SelectListItem>(); 
     Dictionary<string, string> enumItems = enumType.GetDisplayNames(htmlHelper.ViewContext.HttpContext); 
     foreach (KeyValuePair<string, string> pair in enumItems) 
      list.Add(new SelectListItem() { Value = pair.Key, Text = pair.Value }); 
     return htmlHelper.DropDownListFor(expression, list); 
    } 

    /// <summary> 
    /// return the items of enum paired with its DisplayName. 
    /// </summary> 
    /// <param name="enumeration">enumeration type to be processed.</param> 
    /// <returns></returns> 
    public static Dictionary<string, string> GetDisplayNames(this Type enumeration, HttpContextBase httpContext) 
    { 
     if (!enumeration.IsEnum) 
     { 
      throw new ArgumentException("passed type must be of Enum type", "enumerationValue"); 
     } 

     Dictionary<string, string> displayNames = new Dictionary<string, string>(); 
     var members = enumeration.GetMembers().Where(m => m.MemberType == MemberTypes.Field); 

     foreach (MemberInfo member in members) 
     { 
      var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false); 
      if (attrs.Count() != 0) 
       if (((DisplayAttribute)attrs[0]).ResourceType != null) 
       { 
        displayNames.Add(member.Name, ((DisplayAttribute)attrs[0]).GetName();); 
       } 
       else 
       { 
        displayNames.Add(member.Name, ((DisplayAttribute)attrs[0]).Name); 
       } 
     } 
     return displayNames; 
    } 

枚舉的定義有看起來像現在這樣:

public enum Gender 
{ 
    [Display(Name = "Male", ResourceType = typeof(mynamespace.App_LocalResources.Shared))] 
    Male = 1, 

    [Display(Name = "Female", ResourceType = typeof(mynamespace.App_LocalResources.Shared))] 
    Female = 2, 

} 

它可以在一個視圖中使用相同的方式,例如(剃刀):

@Html.DropDownListFor(model => model.Gender, typeof(Gender)) 

希望這可以幫助別人!

2

我做了dropdownlistfor方法更容易一點,現在你可以給它一個了selectedValue:

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType) 
{ 
    return DropDownListFor(htmlHelper, expression, enumType, null); 
} 

public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, Type enumType, object selectedValue) 
{ 
    Dictionary<string, string> enumItems = enumType.GetDisplayNames(htmlHelper.ViewContext.HttpContext); 
    return htmlHelper.DropDownListFor(expression, new SelectList(enumItems, "Key", "Value", selectedValue)); 
} 

使用它像這樣在你的視野:

@Html.DropDownListFor(m => m.Gender, typeof(Gender), Model.Gender) 

型號是我的MVC模式其屬性Gender包含DropDownListFor的selectedValue。

17

遲到但我希望這可以幫助別人。理想情況下,你希望所有枚舉按照慣例使用您的枚舉模板,而不是每次都指定一個UIHint,你可以通過創建一個自定義模型元數據提供這樣的成就是:

using System; 
using System.Collections.Generic; 
using System.Web.Mvc; 

public class CustomMetadataProvider : DataAnnotationsModelMetadataProvider 
{ 
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName) { 
     var mm = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 
     if (modelType.IsEnum && mm.TemplateHint == null) { 
      mm.TemplateHint = "Enum"; 
     } 
     return mm; 
    } 
} 

然後,只需在Application_Start註冊它方法Global.asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider(); 

現在所有的枚舉屬性將默認使用您的枚舉模板。

+0

太棒了!好主意。 – 2012-02-07 06:51:58

+0

我在http://odetocode.com/blogs/scott/archive/2012/09/04/working-with-enums-and-templates-in-asp-net-mvc.aspx 的幫助下使用了您的想法工作得很好。謝謝 ;) – 2014-02-09 19:12:50

1

你可以用這個例子.....

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Profile.Data.Enum 
{ 
    public enum EfficiencyType 
    { 
     Good = 1, 
     Excelent = 2, 
     Better = 3 
    } 
} 

擴展方法是....

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace Profile.Web.HtmlHelper 
{ 
    public static class EnumDropDownList 
    { 
     public static HtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression, string firstElement) 
     { 
      var typeOfProperty = modelExpression.ReturnType; 
      if (!typeOfProperty.IsEnum) 
      throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty)); 

      var enumValues = new SelectList(Enum.GetValues(typeOfProperty)); 
      return htmlHelper.DropDownListFor(modelExpression, enumValues, firstElement); 
     } 
    } 
} 

和HTML是....

@Html.DropDownListFor(model => model.EfficiencyType, new SelectList(Enum.GetValues(typeof(EfficiencyType)), Model.EfficiencyType), "--Select--") 
相關問題