1. 程式人生 > >C#——後臺管理端多級選單的生成方式

C#——後臺管理端多級選單的生成方式

現在大多的應用程式(後端)都有選單,不管是在左側還是上面,介面基本都是基於現有的UI框架或者網上找的單獨的選單的外掛。而實現的方式,大部分都是使用的AJAX形式來完成。前段時間,在總結一些過往的專案時,發現了一些不同的實現的方式,這裡想總結一下。所以也就有了這篇文章~~

我建立的測試Demo是使用的MVC的模式,選單是使用的網上找的第三方外掛,實現多級(無限)的頂部選單。直接上程式碼來說明~

開始之前,先看下css和js的引用情況以及一些需要的準備工作:

css

<link href="~/scripts/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" href="~/scripts/css/font-awesome.min.css" media="screen">
<link rel="stylesheet" href="~/scripts/css/zlight.menu.css" media="screen">

js

<script src="~/scripts/jquery-1.9.1.min.js"></script>
<script src="~/scripts/bootstrap.min.js"></script>
<script src="~/scripts/jquery.zlight.menu.1.0.min.js"></script>
<!--自定義的js,編寫自己的js生成選單-->
<script src="~/scripts/Home/home.js"></script>

模擬的資料來源

        /// <summary>
        /// 得到資料來源
        /// </summary>
        /// <returns></returns>
        private List<MenuModel> GetData()
        {
            var lstData = new List<MenuModel>();
            //頂層選單
            lstData.Add(new MenuModel() { Id = "1", MenuName = "Blog", MenuUrl = "#", ParentId = "#", SortNumb = 1 });
            lstData.Add(new MenuModel() { Id = "2", MenuName = "Portfolio", MenuUrl = "#", ParentId = "#", SortNumb = 2 });
            lstData.Add(new MenuModel() { Id = "3", MenuName = "Pages", MenuUrl = "#", ParentId = "#", SortNumb = 3 });
            lstData.Add(new MenuModel() { Id = "4", MenuName = "Contact", MenuUrl = "#", ParentId = "#", SortNumb = 4 });
            lstData.Add(new MenuModel() { Id = "5", MenuName = "About", MenuUrl = "#", ParentId = "#", SortNumb = 5 });
            //第二層
            lstData.Add(new MenuModel() { Id = "11", MenuName = "LINK1", MenuUrl = "#", ParentId = "1", SortNumb = 1 });
            lstData.Add(new MenuModel() { Id = "12", MenuName = "LINK2", MenuUrl = "#", ParentId = "1", SortNumb = 2 });
            lstData.Add(new MenuModel() { Id = "13", MenuName = "LINK3", MenuUrl = "#", ParentId = "1", SortNumb = 3 });

            lstData.Add(new MenuModel() { Id = "31", MenuName = "LINK1", MenuUrl = "#", ParentId = "3", SortNumb = 1 });
            lstData.Add(new MenuModel() { Id = "32", MenuName = "DROPDOWN", MenuUrl = "#", ParentId = "3", SortNumb = 2 });
            lstData.Add(new MenuModel() { Id = "33", MenuName = "LINK2", MenuUrl = "#", ParentId = "3", SortNumb = 3 });
            //第三層
            lstData.Add(new MenuModel() { Id = "321", MenuName = "LINK1", MenuUrl = "#", ParentId = "32", SortNumb = 1 });
            lstData.Add(new MenuModel() { Id = "322", MenuName = "LINK2", MenuUrl = "#", ParentId = "32", SortNumb = 2 });
            lstData.Add(new MenuModel() { Id = "323", MenuName = "LINK3", MenuUrl = "#", ParentId = "32", SortNumb = 3 });
            lstData.Add(new MenuModel() { Id = "324", MenuName = "DROPDOWN", MenuUrl = "#", ParentId = "32", SortNumb = 4 });
            //第四層
            lstData.Add(new MenuModel() { Id = "3241", MenuName = "LINK1", MenuUrl = "#", ParentId = "324", SortNumb = 1 });
            lstData.Add(new MenuModel() { Id = "3242", MenuName = "LINK2", MenuUrl = "#", ParentId = "324", SortNumb = 2 });


            return lstData;
        }

後臺選單實現需要的方法

        /// <summary>
        /// 生成選單拼接字串
        /// </summary>
        /// <returns></returns>
        private string GenerateMenu()
        {
            StringBuilder sb = new StringBuilder();
            var lstAll = GetData();
            var lstParent = lstAll.FindAll(x => x.ParentId == "#").ToList();
            var lstChilds = lstAll.FindAll(x => x.ParentId != "#").ToList();

            if (lstParent.Any())
            {
                foreach (var top in lstParent)
                {
                    var lstOnes = lstChilds.FindAll(x => x.ParentId == top.Id).OrderBy(x => x.SortNumb).ToList();
                    if (lstOnes.Any())
                    {
                        sb.Append("<li class=\"zlight-dropdown\">")
                            .AppendFormat("<a href = \"{0} \"> {1}<i class=\"icon-angle-down\"></i></a>", top.MenuUrl, top.MenuName)
                            .Append("<ul class=\"zlight-submenu\">");
                        GetChild(sb, lstChilds, lstOnes);
                        sb.Append("</ul></li > ");
                    }
                    else
                    {
                        sb.AppendFormat("<li><a href = \"{0} \"> {1} </a></li>", top.MenuUrl, top.MenuName);
                    }
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 得到子選單項
        /// </summary>
        /// <param name="sb">StrignBuilder物件</param>
        /// <param name="lstChilds">所有子節點集合</param>
        /// <param name="lstOnes">“父”節點集合</param>
        private static void GetChild(StringBuilder sb, List<MenuModel> lstChilds, List<MenuModel> lstOnes)
        {
            foreach (var chld in lstOnes)
            {
                var lstTwos = lstChilds.FindAll(x => x.ParentId == chld.Id).OrderBy(x => x.SortNumb).ToList();
                if (lstTwos.Any())
                {
                    sb.Append("<li class=\"zlight-dropdown\">")
                           .AppendFormat("<a href = \"{0} \"> {1}<i class=\"icon-angle-down\"></i></a>", chld.MenuUrl, chld.MenuName)
                           .Append(" <ul class=\"zlight-submenu\">");
                    GetChild(sb, lstChilds, lstTwos);
                    sb.Append("</ul></li> ");
                }
                else
                {
                    sb.AppendFormat("<li><a href = \"{0} \" target = \"_blank\"> {1} </a></li>", chld.MenuUrl, chld.MenuName);
                }
            }
        }

 

1、Ajax方式

html部分

<div class="row">
    <div class="col-lg-12">
        <h4>第一種(AJAX):</h4>
    </div>
 </div>

<div class="row">
   <div class="col-lg-12">
       <nav id="zlight-nav">
            <ul id="zlight-main-nav">
                <li class="zlight-active"><a href="/">Home</a></li>
            </ul>
            <!-- MOBILE NAV -->
            <div id="zlight-mobile-nav">
                 <span>Menu</span>
                 <i class="icon-reorder zlight-icon"></i>
                 <select></select>
            </div>
       </nav> <!-- nav close -->
   </div>
</div>

js(注意放到頁面載入完成事件中)

$.ajax({
        url: "/Home/GetTopMenu",
        type: 'POST',
        async: false,
        dataType: 'text',
        timeout: 20000,
        error: function () {
            alert('Error loading XML document');
        },
        success: function (result) {
            $("#zlight-main-nav").append(result);
            $('#zlight-nav').zlightMenu();
        }
    });

後臺的Action方法

[HttpPost]
public ActionResult GetTopMenu()
{
    return Content(GenerateMenu());
}

2、ViewBag方式

html部分

        <div class="row">
            <div class="col-lg-12">
                <h4>第二種(ViewBag):</h4>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-12">
                <nav id="zlight-nav" class="razer">
                    <ul id="zlight-main-nav">
                        <li class="zlight-active"><a href="/">Home</a></li>
                        @Html.Raw(@ViewBag.TopMenu)
                    </ul>
                    <!-- MOBILE NAV -->
                    <div id="zlight-mobile-nav">
                        <span>Menu</span>
                        <i class="icon-reorder zlight-icon"></i>
                        <select></select>
                    </div>
                </nav>
            </div>
        </div>

js

$('.razer').zlightMenu();

後臺程式碼

// GET: Home
public ActionResult Index()
{
     ViewBag.TopMenu = GenerateMenu();

     return View();
}

3、Razer遞迴方式(很少用)

html部分

        <div class="row">
            <div class="col-lg-12">
                <h4>第三種(Razer遞迴):</h4>
            </div>
        </div>
        <div class="row">
            <div class="col-lg-12">
                <nav id="zlight-nav" class="razerdigui">
                    <ul id="zlight-main-nav">
                        <li class="zlight-active"><a href="/">Home</a></li>
                        @{
                            var lstData = ViewBag.MenuDataList as List<MenuModel>;
                            @helper DisplayChildMenu(List<MenuModel> lstChilds, List<MenuModel> lstOnes)
                            {
foreach (var chld in lstOnes)
{
    var lstTwos = lstChilds.FindAll(x => x.ParentId == chld.Id).OrderBy(x => x.SortNumb).ToList();
    if (lstTwos.Any())
    {
            <li class="zlight-dropdown">
                <a href="@chld.MenuUrl" target="_blank">@chld.MenuName <i class="icon-angle-down"></i></a>
                <ul class="zlight-submenu">
                    @DisplayChildMenu(lstChilds, lstTwos)
                </ul>
            </li>
    }
    else
    {
            <li><a href="@chld.MenuUrl" target="_blank">@chld.MenuName</a></li>
    }
}
}
                            var lstParent = lstData.FindAll(x => x.ParentId == "#").ToList();
                            var lstChilds = lstData.FindAll(x => x.ParentId != "#").ToList();
                            if (lstParent.Any())
                            {
                                foreach (var top in lstParent)
                                {
                                    var lstOnes = lstChilds.FindAll(x => x.ParentId == top.Id).OrderBy(x => x.SortNumb).ToList();
                                    if (lstOnes.Any())
                                    {
                                        <li class="zlight-dropdown">
                                            <a href="@top.MenuUrl">@top.MenuName <i class="icon-angle-down"></i></a>
                                            <ul class="zlight-submenu">
                                                @DisplayChildMenu(lstChilds, lstOnes)
                                            </ul>
                                        </li>
                                    }
                                    else
                                    {
                                        <li><a href="@top.MenuUrl">@top.MenuName</a></li>
                                    }
                                }
                            }
                        }
                    </ul>
                    <!-- MOBILE NAV -->
                    <div id="zlight-mobile-nav">
                        <span>Menu</span>
                        <i class="icon-reorder zlight-icon"></i>
                        <select></select>
                    </div>
                </nav>
     
            </div>
        </div>

js部分

$('.razerdigui').zlightMenu();

後臺部分

// GET: Home
public ActionResult Index()
{
    ViewBag.MenuDataList = GetData();

    return View();
}

後記:在非MVC模式下,第一中Ajax方式是非常常用的,即使在MVC模式下仍常用。第二種和第三中在MVC模式下用都可以,Razer的遞迴之前並沒有注意到,一次突發奇想就度娘了下,結果還真有。至於需要用哪種,看個人吧