zoukankan      html  css  js  c++  java
  • MVC中下拉框显示枚举项

    本篇将通过3种方式,把枚举项上的自定义属性填充到下拉框:
    1、通过控制器返回List<SelectListItem>类型给前台视图
    2、通过为枚举类型属性打上UIHint属性让模版显示枚举项
    3、通过自定义元数据提供器DataAnnotationsModelMetadataProvider让模版显示枚举项

     

    我们经常会把类型为Int16的属性通过枚举来获得。比如:

    public class SomeClass
    {
        public int16 Status{get;set;}
    }

    对应的枚举:

    public enum StatusEnum
    {
        Enable = 0,
        Disable = 1
    }

    在MVC视图中可能会这样写:

    <select id="sel">
       <option value="">==选择状态==</option>
       <option value="0">启用</option>
       <option value="1">禁用</option>
    </select>

    如果枚举的项发生变化怎么办?比如:

    public enum StatusEnum
    {
        Enable = 0,
        Disable = 1,
        NeverComeback = 2
    }

    如果修改每一页的代码,显然是不合理的。最理想的做法是:为每一个枚举项打上属性,显示的时候直接读取枚举以及枚举项属性值。

     

      通过控制器返回List<SelectListItem>类型给前台视图

    定义一个Model,其中有一个类型为Int16的属性Status,这个属性用来接收枚举值。

    using System;
    using System.ComponentModel.DataAnnotations;
     
    namespace MvcApplication1.Models
    {
        public class Stadium
        {
            public int Id { get; set; }
     
            [Display(Name = "场馆名称")]
            public string Name { get; set; }
     
            [Display(Name = "是否启用")]
            public Int16 Status { get; set; }
        }
    }

    为每个枚举项打上的属性需要我们自定义,通过构造函数接收名称,并提供一个属性供外部访问。

    using System;
     
    namespace MvcApplication1.Extension
    {
        public class EnumDisplayNameAttribute : Attribute
        {
            private string _displayName;
     
            public EnumDisplayNameAttribute(string displayName)
            {
                this._displayName = displayName;
            }
     
            public string DisplayName
            {
                get { return _displayName; }
            }
        }
    }

    为每个枚举项打上自定义属性。

    using MvcApplication1.Extension;
     
    namespace MvcApplication1.Models.Enum
    {
        public enum StatusEnum
        {
            [EnumDisplayName("启用")]
            Enable = 0,
            [EnumDisplayName("禁用")]
            Disable =  1
        }
    }

    我们的目的是在控制器获取List<SelectListItem>集合,然后传递到前台视图。现在,枚举和枚举项上的自定义属性都有了,有必要创建一个帮助类来帮我们获取List<SelectListItem>集合。

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web.Mvc;
     
    namespace MvcApplication1.Extension
    {
        public class EnumExt
        {
            /// <summary>
            /// 根据枚举成员获取自定义属性EnumDisplayNameAttribute的属性DisplayName
            /// </summary>
            /// <param name="e"></param>
            /// <returns></returns>
            public static string GetEnumCustomDescription(object e)
            {
                //获取枚举的Type类型对象
                Type t = e.GetType();
     
                //获取枚举的所有字段
                FieldInfo[] ms = t.GetFields();
     
                //遍历所有枚举的所有字段
                foreach (FieldInfo f in ms)
                {
                    if (f.Name != e.ToString())
                    {
                        continue;
                    }
     
                    //第二个参数true表示查找EnumDisplayNameAttribute的继承链
                    if (f.IsDefined(typeof (EnumDisplayNameAttribute), true))
                    {
                        return
                            (f.GetCustomAttributes(typeof(EnumDisplayNameAttribute), true)[0] as EnumDisplayNameAttribute)
                                .DisplayName;
                    }
                }
     
                //如果没有找到自定义属性,直接返回属性项的名称
                return e.ToString();
            }
     
            /// <summary>
            /// 根据枚举,把枚举自定义特性EnumDisplayNameAttribut的Display属性值撞到SelectListItem中
            /// </summary>
            /// <param name="enumType">枚举</param>
            /// <returns></returns>
            public static List<SelectListItem> GetSelectList(Type enumType)
            {
                List<SelectListItem> selectList = new List<SelectListItem>();
                foreach (object e in Enum.GetValues(enumType))
                {
                    selectList.Add(new SelectListItem(){Text = GetEnumCustomDescription(e),Value = ((int)e).ToString()});
                }
                return selectList;
            }
        }
    }
     

     

    在控制器中,通过ViewData把List<SelectListItem>集合往前台传。控制器包含2个方法,一个方法用来显示创建视图界面,另一个用来显示编辑视图界面。

            //创建
            public ActionResult Index()
            {
                ViewData["s"] = EnumExt.GetSelectList(typeof (StatusEnum));
                return View(new Stadium());
            }
     
            //编辑
            public ActionResult Edit()
            {
                Stadium s = new Stadium()
                {
                    Id = 2,
                    Name = "水立方",
                    Status = (short)StatusEnum.Disable
                };
                ViewData["s"] = EnumExt.GetSelectList(typeof(StatusEnum));
                return View(s);
            }

    在强类型的创建视图界面中,通过@Html.DropDownListFor(model => model.Status,(List<SelectListItem>)ViewData["s"])接收来自控制器的数据。

    @model MvcApplication1.Models.Stadium
     
    @{
        ViewBag.Title = "Index";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
     
    <h2>Index</h2>
     
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
     
        <fieldset>
            <legend>Stadium</legend>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Status)
            </div>
            <div class="editor-field">
                @Html.DropDownListFor(model => model.Status,(List<SelectListItem>)ViewData["s"])
                @Html.ValidationMessageFor(model => model.Status)
            </div>
     
            <p>
                <input type="submit" value="添加" />
            </p>
        </fieldset>
    }
     
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
     

     

    在强类型的编辑视图界面中,同样通过@Html.DropDownListFor(model => model.Status,(List<SelectListItem>)ViewData["s"])接收来自控制器的数据。

    @model MvcApplication1.Models.Stadium
     
    @{
        ViewBag.Title = "Edit";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
     
    <h2>Edit</h2>
     
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
     
        <fieldset>
            <legend>Stadium</legend>
     
            @Html.HiddenFor(model => model.Id)
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Status)
            </div>
            <div class="editor-field">
                 @Html.DropDownListFor(model => model.Status,(List<SelectListItem>)ViewData["s"])
                @Html.ValidationMessageFor(model => model.Status)
            </div>
     
            <p>
                <input type="submit" value="编辑" />
            </p>
        </fieldset>
    }
     
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
     

     

    创建界面:
    1

     

    编辑界面:
    2

     

      通过为枚举类型属性打上UIHint属性让模版显示枚举项

    由于模版是根据属性类型来判断的,再定义一个Model,其中一个属性类型是枚举。

    using System.ComponentModel.DataAnnotations;
    using MvcApplication1.Models.Enum;
     
    namespace MvcApplication1.Models
    {
        public class Stadium1
        {
            public int Id { get; set; }
     
            [Display(Name = "场馆名称")]
            public string Name { get; set; }
     
            [Display(Name = "是否启用")]
            public StatusEnum Status { get; set; } 
        }
    }

     

    在Views/Shared/EditorTemplates文件夹下创建Enum.cshtml,用来处理类型为Enum的属性。

    @using System.ComponentModel.DataAnnotations
    @using System.Reflection
    @using MvcApplication1.Extension
     
    @{
        var selectList = new List<SelectListItem>();
        string optionLabel = null;
        object htmlAttributes = null;
        var enumType = (Type)Model.GetType();
        foreach (var value in Enum.GetValues(enumType))
        {
            var field = enumType.GetField(value.ToString());
            var option = new SelectListItem() {Value = value.ToString()};
            var display = field.GetCustomAttributes(typeof (EnumDisplayNameAttribute), false).FirstOrDefault() as EnumDisplayNameAttribute;
            if (display != null)
            {
                option.Text = display.DisplayName;
            }
            else
            {
                option.Text = value.ToString();
            }
            option.Selected = object.Equals(value, Model);
            selectList.Add(option);
        }
    }
     
    @Html.DropDownList("",selectList, optionLabel, htmlAttributes)
     

     

    控制器中有2个方法用来显示创建和编辑视图界面。

            //创建
            public ActionResult TemplateCreate()
            {
                return View(new Stadium1());
            }
     
            //编辑
            public ActionResult TemplateEdit()
            {
                Stadium1 s = new Stadium1()
                {
                    Id = 2,
                    Name = "水立方",
                    Status = StatusEnum.Disable
                };
                return View(s);
            }

     

    强类型的创建视图界面:

    @model MvcApplication1.Models.Stadium1
     
    @{
        ViewBag.Title = "TemplateCreate";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
     
    <h2>TemplateCreate</h2>
     
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
     
        <fieldset>
            <legend>Stadium</legend>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Status)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Status)
                @Html.ValidationMessageFor(model => model.Status)
            </div>
     
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }
     
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
     


    强类型的编辑视图界面:

    @model MvcApplication1.Models.Stadium1
     
    @{
        ViewBag.Title = "TemplateEdit";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
     
    <h2>TemplateEdit</h2>
     
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
     
        <fieldset>
            <legend>Stadium</legend>
     
            @Html.HiddenFor(model => model.Id)
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Name)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
     
            <div class="editor-label">
                @Html.LabelFor(model => model.Status)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Status)
                @Html.ValidationMessageFor(model => model.Status)
            </div>
     
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }
     
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
     

     

    最后,给Stadium1的枚举属性,打上UIHint属性,指明使用公共Enum类型模版Views/Shared/EditorTemplates/Enum.cshtml。

    using System.ComponentModel.DataAnnotations;
    using MvcApplication1.Models.Enum;
     
    namespace MvcApplication1.Models
    {
        public class Stadium1
        {
            public int Id { get; set; }
     
            [Display(Name = "场馆名称")]
            public string Name { get; set; }
     
            [Display(Name = "是否启用")]
            [UIHint("Enum")]
            public StatusEnum Status { get; set; } 
        }
    }
     

     

    创建视图界面:
    3

    编辑视图界面:
    4

     

      通过自定义元数据提供器DataAnnotationsModelMetadataProvider让模版显示枚举项

    如果觉得为属性打上[UIHint("Enum")]属性麻烦的话,还可以通过数据提供器,为所有类型为Enum的属性指明模版。

    5

     

    当然自定义的元数据提供器是需要在全局中注册的。

        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
     
                WebApiConfig.Register(GlobalConfiguration.Configuration);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
     
                //注册自定义元数据提供其
                ModelMetadataProviders.Current = new CustomMetadataProvider();
            }
        }

    现在可以把Stadium的[UIHint("Enum")]注释掉。

     

      总结

    如果,我们想在下拉框中显示枚举项,首先给枚举项打上自定义属性,通过反射可以拿到自定义属性的相关属性值。

    如果,想在控制器方法中获取List<SelectListItem>集合往前台传,我们可以封装一个方法,根据枚举返回List<SelectListItem>集合;

    如果想根据属性的类型显示枚举模版,要么给枚举属性打上[UIHint("Enum")],要么在全局自定义一个DataAnnotationsModelMetadataProvider。

  • 相关阅读:
    Hibernate延迟加载机制
    Hibernate中Criteria的完整用法
    HibernateTemplate的常规用法
    Java各类在线API
    HibernateTemplate的常规用法
    Hibernate中Criteria的完整用法
    Java各类在线API
    Hibernate3的DetachedCriteria使用
    Hibernate延迟加载机制
    Hibernate3的DetachedCriteria使用
  • 原文地址:https://www.cnblogs.com/darrenji/p/3658375.html
Copyright © 2011-2022 走看看