Pregunta

¿Cómo puedo hacer una plantilla editor predeterminado para las enumeraciones? Por lo cual quiero decir: puedo hacer algo como esto:

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

Y poner esto en el EditorTemplates carpeta bajo el nombre Enum.ascx?

Aquí hay una solución para mi problema que he intentado, pero no es lo que necesito.

Aquí está mi enumeración:

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

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

He hecho una plantilla llamada GenderEnum.acsx y la puso en la carpeta Shared/EditorTemplates. Esta es la plantilla:

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

Por supuesto, el método es mi propia:

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

    }

Sin embargo, a pesar de que esto funcionó para mí, no es lo que estoy preguntando. En su lugar, necesito el siguiente al trabajo:

Código de 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()) %>

Con esto no tendría que hacer una plantilla para cada enumeración más.

¿Fue útil?

Solución 2

Gracias a todos por sus contribuciones
Yngvebn, he intentado la solución (en su último comentario) antes, pero la única cosa que no me hago es la <dynamic>, he utilizado en lugar <Enum> de tipo genérico.

Por fin, la solución es:
crear una plantilla llamada Enum.acsx y se pone debajo de los Vistas \ 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())%>

y en su Entidad:

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

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

y de nuevo hay Métodos Extention:

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

    }

Otros consejos

tarde para responder, pero espero que esto ayude a otros. Lo ideal es que todas las enumeraciones de usar la plantilla de Enum por convenio, no especificando un UIHint cada vez, y que puede lograr que mediante la creación de un proveedor de metadatos modelo personalizado de esta manera:

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

A continuación, sólo tiene que registrarse en el método de Application_Start Global.asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider();

Ahora todas sus propiedades de enumeración usarán su plantilla Enum por defecto.

Aquí hay un ayudante que hice para este .. En su opinión, sólo tiene que hacer:

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

para el texto en el menú desplegable real que va a buscar un recurso en el recurso-archivo que coincida con el nombre de la enumeración, de lo contrario sólo escribir el propio Enumtext real.

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

También necesitará mi clase Tag sobrecargado si se quiere que funcione sin volver a escribir ..

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, que modificó la versión de la localización también el apoyo con recursos. Por lo tanto he cambiado el DescriptionAttribute a la DisplayAttribute de los DataAnnotations espacio de nombres

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

La definición de una enumeración tiene que ver como esta ahora:

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,

}

que puede ser utilizado en una vista de la misma manera, por ejemplo, (Razor):

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

Espero que esto ayude a alguien!

Me hizo el método dropdownlistfor un poco más fácil y ahora le puede dar una SelectedValue con ella:

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

utilizar de esta manera en su opinión:

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

Modelo es mi modelo MVC y su propiedad Género contiene el SelectedValue para la DropDownListFor.

No creo que hay una manera predeterminada para definir un editor para todo tipo de enumeración, porque lo que pueda desear un comportamiento diferente dependiendo de la situación. Por ejemplo, tal vez usted tiene un [Banderas] enumeración y quiere múltiples de selección, o si desea una lista desplegable, o si desea botones de radio.

Además, en general, usted va a querer algún tipo de cadena de visualización significativa más allá de lo que puede lograr en las limitaciones de denominación de variables.

Desde luego asignación a una propiedad de tipo de enumeración trabaja fuera de la caja, pero ¿cómo se obtiene que el valor va a ser de usted.

Casi seguro que esto funciona fuera de la caja.


Trate de nombrar a su plantilla el mismo nombre que su enumeración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top