How to make a default editor template for enums?

前端 未结 7 992
星月不相逢
星月不相逢 2020-12-08 03:11

How can I make a default editor template for enums? By which I mean: can I do something like this:

<%@ Control Language=\"C#\" Inherits=\"System.Web.Mvc.V         


        
相关标签:
7条回答
  • 2020-12-08 03:31

    Yes

    Almost sure this works out of the box.


    Try naming your template the same name as your enum.

    0 讨论(0)
  • 2020-12-08 03:36

    I made the dropdownlistfor method a bit easier and now you can give a selectedValue with it:

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

    Use it like this in your View:

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

    Model is my MVC Model and its property Gender contains the selectedValue for the DropDownListFor.

    0 讨论(0)
  • 2020-12-08 03:40

    Late to answer but I hope this helps others. Ideally you want all enums to use your Enum template by convention, not by specifying a UIHint each time, and you can accomplish that by creating a custom model metadata provider like this:

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

    Then simply register it in the Application_Start method of Global.asax.cs:

    ModelMetadataProviders.Current = new CustomMetadataProvider();
    

    Now all your enum properties will use your Enum template by default.

    0 讨论(0)
  • 2020-12-08 03:44

    I don't think there is a default way to define an editor for all enum types because you could want different behavior depending on the situation. For example, maybe you have a [Flags] enum and want multi select, or you want a dropdownlist, or you want radio buttons.

    Plus, generally you are going to want some sort of meaningful display string beyond what you can accomplish in the variable naming limitations.

    Certainly assigning to a property of type enum works out of the box but how you get that value is going to be up to you.

    0 讨论(0)
  • Nour Sabony, I modified your version to also support localization with resources. Therefore I changed the DescriptionAttribute to the DisplayAttribute of the DataAnnotations namespace

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

    The definition of an enum has to look like this now:

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

    it can be used in a View in the same way, e.g. (Razor):

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

    Hope this helps someone!

    0 讨论(0)
  • 2020-12-08 03:47

    Thank you all for your contributions
    Yngvebn, i tried your solution (in your last comment) before, but the only thing i didn't do is the <dynamic>, i used instead <Enum> in generic type.

    at last the solution is :
    create a template named Enum.acsx and put it under the 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())%>
    

    and in your Entity:

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

    and again there is Extention Methods:

    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;
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题