Как я могу сделать шаблон редактора по умолчанию для перечислений? Под этим я подразумеваю: могу ли я сделать что-то вроде этого:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %>
<% -- any code to read the enum and write a dropdown -->
И поместить это в папку EditorTemplates под именем Enum.ascx
?
Вот обходной путь для моей проблемы, который я пробовал, но это не то, что мне нужно.
Вот мой Enum:
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()) %>
При этом мне больше не нужно будет создавать шаблон для каждого перечисления.
Спасибо всем за ваш вклад
Yngvebn, я пробовал ваше решение (в вашем последнем комментарии) раньше, но единственное, что я не сделал, это
, я использовал вместо него
в общем типе .
наконец решение:
создайте шаблон с именем Enum.acsx и поместите его в Views \ Shared \ 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;
}
}
Я не думаю, что существует способ определения редактора по умолчанию для всех типов перечислений, потому что в зависимости от ситуации может потребоваться различное поведение. Например, возможно, у вас есть перечисление [Flags] и вы хотите множественный выбор, или вам нужен раскрывающийся список, или вам нужны переключатели.
Кроме того, обычно вам может потребоваться какая-то значимая строка отображения, выходящая за рамки того, что вы можете сделать с помощью ограничений именования переменных.
Конечно, назначение свойству типа enum работает из коробки, но как вы получите это значение, зависит от вас.
Вот помощник, который я сделал для этого .. В вашем представлении вы можете просто сделать:
<%= Html.DropDownForEnum<MyEnum>("some-name-for-dropdown", MyEnum.TheFirstValue) %>
для текста в фактическом раскрывающемся списке он будет искать ресурс в файле ресурсов, который соответствует имени перечисления, в противном случае просто напишите фактический текст перечисления.
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());
}
Вам также понадобится мой перегруженный класс Tag, если вы хотите, чтобы он работал без перезаписи ..
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;
}
}
Да
Почти уверен, что это работает из коробки.
Попробуйте назвать свой шаблон таким же именем, как и ваше перечисление.