visual studio microsoft español descargar community asp.net asp.net-mvc enums mvc-editor-templates

asp.net - studio - ¿Cómo hacer una plantilla de editor por defecto para enums?



visual studio installer (8)

Aquí hay un ayudante que hice para esto ... En su Vista, simplemente puede hacer:

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

para el texto en el menú desplegable real, buscará un Recurso en el archivo de recursos que coincida con el nombre de la enumeración, de lo contrario, simplemente escriba el 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ás mi clase de etiqueta sobrecargada si quieres que funcione sin reescritura.

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

¿Cómo puedo hacer una plantilla de editor predeterminada para enumeraciones? Por lo que 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 la carpeta EditorTemplates bajo el nombre Enum.ascx ?

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

Aquí está mi Enum:

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

Hice una plantilla llamada GenderEnum.acsx y la puse en la carpeta Shared/EditorTemplates . Aquí está 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 que el método es mío:

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, aunque esto funcionó para mí, no es lo que estoy preguntando. En su lugar, necesito lo siguiente para trabajar:

Código para 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 ya no tendría que hacer una plantilla para cada enumeración.


Gracias a todos por sus contribuciones.
Yngvebn, probé tu solución (en tu último comentario) antes, pero lo único que no hice fue <dynamic> , usé <Enum> en tipo genérico.

por fin la solución es:
cree una plantilla llamada Enum.acsx y colóquela bajo las 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 otra vez hay métodos de extensión:

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


Hice la lista desplegable para el método un poco más fácil y ahora puede dar un Valor seleccionado con él:

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

Úsalo así en tu vista:

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

Model es mi modelo MVC y su propiedad Gender contiene el valor seleccionado para DropDownListFor.


No creo que haya una forma predeterminada de definir un editor para todos los tipos de enumeración porque es posible que desee un comportamiento diferente según la situación. Por ejemplo, tal vez tenga una enumeración [Indicadores] y desee la selección múltiple, o desee una lista desplegable, o desee los botones de opción.

Además, generalmente querrá algún tipo de cadena de visualización significativa más allá de lo que puede lograr en las limitaciones de nombres de variables.

Ciertamente, la asignación a una propiedad de tipo enum trabaja fuera de la caja, pero la forma en que obtenga ese valor dependerá de usted.


Nour Sabony, modifiqué tu versión para que también sea compatible con la localización con recursos. Por lo tanto, cambié DescriptionAttribute al DisplayAttribute del espacio de nombres 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; }

La definición de una enumeración tiene que verse así 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, }

se puede usar en una Vista de la misma manera, por ejemplo, (Razor):

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

¡Espero que esto ayude a alguien!


Puedes usar este ejemplo .....

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

método de extensión es ...

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

y el html es ....

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


Casi seguro que esto funciona fuera de la caja.

Intenta nombrar a tu plantilla el mismo nombre que tu enumeración.


Tarde para responder pero espero que esto ayude a otros. Lo ideal es que desee que todas las enumeraciones utilicen su plantilla Enum por convención, no especificando un UIHint cada vez, y puede lograrlo creando un proveedor de metadatos de modelo personalizado como este:

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

Luego simplemente regístrelo en el método Application_Start de Global.asax.cs:

ModelMetadataProviders.Current = new CustomMetadataProvider();

Ahora todas las propiedades de enumeración usarán tu plantilla de enumeración de forma predeterminada.