Вопрос

Как я могу сделать шаблон редактора по умолчанию для Enums? К которому я имею в виду: могу ли я сделать что-то вроде этого:

<%@ 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()) %>

С этим мне больше не придется сделать шаблон для каждого каната.

Это было полезно?

Решение 2

Спасибо всем за ваш вклад
Yngvebn, я попробовал ваше решение (в вашем последнем комментарии) раньше, но единственное, что я не сделал, это <dynamic>, я использовал вместо этого <Enum> в общем типе.

Наконец решение:
создать шаблон с именем enum.acsx и положить его под Просмотров 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;
        }

    }

Другие советы

Поздно ответить, но я надеюсь, что это помогает другим. В идеале вы хотите, чтобы все его перечислены использовать свой шаблон ENUM по соглашению, а не указав 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 of Global.Asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider();

Теперь все ваши свойства Enum будут использовать ваш шаблон Enum по умолчанию.

Вот помощник, который я сделал для этого .. В вашем виде вы можете просто сделать:

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

Для текста в фактическом раскрывающемся списке он будет искать ресурс в ресурсе-файле, который соответствует названию enum, в противном случае просто напишите сам фактический 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;
}
}

Nour Sabony, я изменил вашу версию, чтобы также поддерживать локализацию с ресурсами. Поэтому я изменил описаниеAttribute на дисцидентатрибуте пространства имен даматиканотаций

    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;
    }

Определение enum должно выглядеть так:

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))

Надеюсь, это поможет кому-то!

Я немного проще сделал DropDownlistFor, и теперь вы можете дать вам выбранную информацию:

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, и ее гендер недвижимости содержит выбранную информацию для DropDowlistFor.

Я не думаю, что есть способ определения редактора для всех типов Enum, потому что вы можете захотеть разное поведение в зависимости от ситуации. Например, может быть, у вас есть [флаги] enum и нужны multi select, или вы хотите выбросить список, или вы хотите, чтобы радио кнопки.

Плюс, как правило, вы собираетесь захотеть какую-то значимую строку отображения за пределами того, что вы можете выполнить в переменных ограничениях именования.

Безусловно присвоение Для свойства типа Enum работает из коробки, но как вы получите эту ценность для вас.

Да

Почти уверен, что это работает из коробки.


Попробуйте назвать ваш шаблон то же имя, что и ваш enum.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top