首頁 > 軟體

ASP.NET MVC下拉框中顯示列舉項

2022-07-31 18:01:22

本篇將通過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")
}

建立介面:

編輯介面:

通過為列舉型別屬性打上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; } 
    }
}

建立檢視介面:

編輯檢視介面:

通過自定義後設資料提供器DataAnnotationsModelMetadataProvider讓模版顯示列舉項

如果覺得為屬性打上[UIHint("Enum")]屬性麻煩的話,還可以通過資料提供器,為所有型別為Enum的屬性指明模版。

當然自定義的後設資料提供器是需要在全域性中註冊的。

    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。

到此這篇關於ASP.NET MVC下拉框中顯示列舉項的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com