關於在MVC中生成下拉框的各種場景應用c

    在建設網站當中,生成下拉框本來是一件非常微不足道的事,但是在實際應用當中,我常常會碰到這樣的一個場景:剛開始設計時僅固定爲幾個下拉選項,但是經過幾次迭代和需求更改之後,這個下拉選項會不斷地被要求改來改去。

當然,我們希望這個下拉框是動態讀取數據庫中的數據,並實現動態的後臺可視化管理,但有些場景下並不會提供一張表數據。

        所以在一次開發中,我突然冒出一個想法。借用類似Dictionary的鍵值映射關係,因爲下拉框元素也剛好可以看成這樣的鍵-值對的形式。

    所以我自定義了一個映射的類如下:

   <span style="font-family:Courier New;">public class MapEntity
    {
        #region 屬性
        /// <summary>
        /// 鍵
        /// </summary>
        public long Key { set; get; }

        /// <summary>
        /// 值
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// 是否啓用
        /// </summary>
        public bool Enable { get; set; }
        #endregion

        #region 構造方法
        /// <summary>
        /// 默認
        /// </summary>
        public MapEntity() { }

        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="key">主鍵</param>
        /// <param name="value">值</param>
        /// <param name="enable">是否啓用標誌, 默認啓用</param>
        public MapEntity(long key, string value, bool enable = true)
        {
            this.Key = key;
            this.Value = value;
        }
        #endregion
    }</span>


因爲在這種景中,所的供的下拉選項僅僅是幾種狀態或是各種選項,這個狀態選項又是跟其它的業務相關聯的,故定義一個枚舉,示例如下:

     <span style="font-family:Courier New;">public enum ActiveStatusEnum : int
    {
        /// <summary>
        /// 未審覈
        /// </summary>
        [Description("未審覈")]
        UnAudit = 1,


        /// <summary>
        /// 等待
        /// </summary>
        [Description("等待")]
        Wait = 2,


        /// <summary>
        /// 就緒
        /// </summary>
        [Description("就緒")]
        Ready = 3,


        /// <summary>
        /// 開始
        /// </summary>
        [Description("開始")]
        Start = 4,


        /// <summary>
        /// 完成
        /// </summary>
        [Description("完成")]
        Finish = 5,


        /// <summary>
        /// 停止
        /// </summary>
        [Description("停止")]
        Stop = -1
    }</span>


然後寫一個輔助類,封裝 方法:

    <span style="font-family:Courier New;">public class MapHelper
    {
        public static MapEntity[] WorkList = new MapEntity[] { 
            new MapEntity( (int)ActiveStatusEnum.UnAudit, "未審覈" ),
            new MapEntity( (int)ActiveStatusEnum.Wait, "等待" ),
            new MapEntity( (int)ActiveStatusEnum.Ready, "準備" ),
            new MapEntity( (int)ActiveStatusEnum.Start, "開始" ),
            new MapEntity( (int)ActiveStatusEnum.Finish, "完成" ),
            new MapEntity( (int)ActiveStatusEnum.Stop, "終止", false),
        };

        #region 生成下拉框元素集合
        /// <summary>
        /// 生成下拉框元素集合
        /// </summary>
        /// <param name="fillArray"></param>
        /// <param name="pId"></param>
        /// <param name="IsNeedAll"></param>
        /// <returns></returns>
        public static List<SelectListItem> GetDropDownList(MapEntity[] fillArray, long pId, bool IsNeedAll = false )
        {
            List<SelectListItem> ReturnObj = new List<SelectListItem>();

            if (pId == Int32.MinValue) //如果等於最小值,則直接返回
            {
                return ReturnObj;
            }

            foreach (var item in fillArray) //遍歷數組元素生成下拉框
            {
                SelectListItem ItemObj = new SelectListItem();
                ItemObj.Text = item.Value;
                ItemObj.Value = item.Key.ToString();
                ItemObj.Selected = item.Key == pId;
                ReturnObj.Add(ItemObj);
            }

            if (IsNeedAll) //是否需要插入全部選項
            {
                SelectListItem ItemObj = new SelectListItem();
                ItemObj.Text = "全部";
                ItemObj.Value = "-1";
                ItemObj.Selected = pId == -1;
                ReturnObj.Add(ItemObj);
            }

            return ReturnObj;
        }
        #endregion


        #region 通過
        /// <summary>
        /// 通過鍵 獲取映射值
        /// </summary>
        /// <param name="fillArray">集合對象</param>
        /// <param name="key">指定鍵</param>
        /// <param name="IsIgnoreEnable">是否忽略"是否啓用"選項,默認否</param>
        /// <returns></returns>
        public static string GetMappingValueByKey(MapEntity[] fillArray, long key, bool IsIgnoreEnable = false)
        {
            foreach (var item in fillArray)
            {
                if (item.Key == key)
                {
                    if ( ( !IsIgnoreEnable && item.Enable ) || IsIgnoreEnable  )
                    {
                        return item.Value;
                    }
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 通過鍵 獲取映射值
        /// </summary>
        /// <param name="fillArray">集合對象</param>
        /// <param name="Value">值</param>
        /// <param name="IsIgnoreEnable">是否忽略"是否啓用"選項,默認否</param>
        /// <param name="IsIgnoreCase">是否忽略大小寫,默認否</param>
        /// <returns>如果集合中的鍵存在-999,則不適合此方法</returns>
        public static long GetMappingKeyByValue(MapEntity[] fillArray, string Value, bool IsIgnoreCase = false, bool IsIgnoreEnable = false)
        {
            if (string.IsNullOrEmpty(Value))
            {
                return -999;
            }

            foreach (var item in fillArray)
            {
                if (IsIgnoreCase)
                {
                    //忽略大小寫
                    if (item.Value.ToLower().Equals(Value.ToLower()))
                    {
                        if ((!IsIgnoreEnable && item.Enable) || IsIgnoreEnable)
                        {
                            return item.Key;
                        }
                    }
                }
                else
                {
                    //不忽略大小寫
                    if (item.Value.Equals(Value))
                    {
                        if ((!IsIgnoreEnable && item.Enable) || IsIgnoreEnable)
                        {
                            return item.Key;
                        }
                    }
                }
            }

            return -999;
        }
        #endregion
    }</span>


最後調用時,如下:

 <span style="font-family:Courier New;"> public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            ViewData["DDList"] = MapHelper.GetDropDownList(
                MapHelper.WorkList, (int)ActiveStatusEnum.UnAudit);

            return View();
        }

    }</span>


所以在下次進行變更的時候,只需要設置Enabled屬性,可以設置啓用或者不啓用,也可以隨時添加新的選項。這樣非常的靈活方便。


當然,這裏其實可以有另外的一種方法,那就是通過反射機制。代碼如下:

     <span style="font-family:Courier New;">   /// <summary>
        /// 
        /// </summary>
        /// <param name="EnumType">枚舉對象的類型</param>
        /// <param name="pId">指定的枚舉名稱</param>
        /// <param name="IsNeedAll">是否需要添加全部選項</param>
        /// <returns></returns>
        public static List<SelectListItem> GetDropDownList(Type EnumType, string pId, bool IsNeedAll = false)
        {
            List<SelectListItem> ResultObj = new List<SelectListItem>();

            //獲取當前對象類型的所有成員
            MemberInfo[] MemberArray = EnumType.GetMembers()
                .Where(s => s.MemberType.Equals(MemberTypes.Field) && !s.Name.Equals("value__")).ToArray();

            bool IsFind = false;
            foreach (var memberItem in MemberArray)
            {
                //獲取當前成員的自定義特性
                IEnumerable<CustomAttributeData> CustomArray = memberItem.CustomAttributes;

                SelectListItem SelObj = new SelectListItem();

                foreach(var customItem in CustomArray)
                {
                    //這裏因爲只設置了DescriptionAttribute,所以在讀取第一條後直接跳出
                    SelObj.Text = customItem.ConstructorArguments[0].Value.ToString();
                    break;
                }

                SelObj.Value = memberItem.Name;
                SelObj.Selected = IsFind = memberItem.Name.Equals(pId);
                ResultObj.Add(SelObj);
            }

            if (IsNeedAll)
            {
                if (IsNeedAll) //是否需要插入全部選項
                {
                    SelectListItem ItemObj = new SelectListItem();
                    ItemObj.Text = "全部";
                    ItemObj.Value = "-1";
                    ItemObj.Selected = !IsFind;
                    ResultObj.Add(ItemObj);
                }
            }

            return ResultObj;
        }</span>



在調用時,只需要傳入如下參數示例:


ViewData["DDList2"] = MapHelper.GetDropDownList(typeof(ActiveStatusEnum), ActiveStatusEnum.UnAudit.ToString());


雖然反射機制也是可以實現,但是卻少了一些控制上的靈活性以及多了一些性能上的損耗,相比之下,自定義的映射類,可以自定義屬性控制開關,添加額外的信息等等。


這只是在寫代碼過程中一些小的思考,希望自己能有更多的這樣的思考,積少成多!加油!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章