MVC樹控件,mvc中應用treeview,實現復選框樹的多層級表單控件


類似於多層級的角色與權限控制功能,用MVC實現MVC樹控件,mvc中應用treeview,實現復選框樹的多層級表單控件。最近我們的項目中需要用到樹型菜單,以前使用WebForm時,樹型菜單有微軟提供的控件,非常方便,但現在需要在asp.netmvc中使用樹形菜單,先說明下我們對樹形菜單的需求:

1,支持CheckBox,允許對菜單項進行選擇;
2,當選擇父菜單時,它下面的子菜單全部選中;
3,當取消父菜單的選中狀態時,下面的子菜單也全部取消;
4,比較方便的與MVC結合;

5,能夠初始化選中狀態。

6,能夠以提交表單的方式,一次性將樹綁定到后台接收的對象。

 

首先菜單數據對象:

完整的 CheckboxTreeHelper.cs 代碼:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.Web.Mvc;
  6 using System.Web.Mvc.Html;
  7 using System.Text;
  8 
  9 /*
 10 author:熊學浩
 11 time:2016年6月5日
 12 description:樹形菜單控件(有問題請致信:xiongzaiqiren@163.com),或者請參考【http://www.cnblogs.com/xiongzaiqiren/ 13 */
 14 namespace System.Web.Mvc
 15 {
 16     /// <summary>
 17     /// 菜單數據對象
 18     /// </summary>
 19     public class CheckboxTreeItem
 20     {
 21         /// <summary>
 22         /// 顯示的文本
 23         /// </summary>
 24         public string Text { get; set; }
 25         /// <summary>
 26         /// 顯示文本對應的值
 27         /// </summary>
 28         public string Value { get; set; }
 29         /// <summary>
 30         /// 是否被選中
 31         /// </summary>
 32         public bool Checked { get; set; }
 33         /// <summary>
 34         /// 結合表單的輔助屬性,View上使用(注意每個層級的索引必需從0開始並且是連續的)
 35         /// </summary>
 36         public string Index { get; set; }
 37 
 38         /// <summary>
 39         /// 子菜單集合
 40         /// </summary>
 41         public IList<CheckboxTreeItem> Items { get; set; }
 42     }
 43 
 44     /// <summary>
 45     /// 復選框樹控件
 46     /// 熊學浩
 47     /// 2016年6月3日
 48     /// </summary>
 49     public static class CheckboxTreeHelper
 50     {
 51         private static bool baselayer;
 52 
 53         public static String CheckboxTree(this HtmlHelper helper, string Name, CheckboxTreeItem Model, out string this_HtmlDomName, bool isChildNode = false)
 54         {
 55             if (null == Model)
 56             {
 57                 this_HtmlDomName = string.Empty;
 58                 return string.Empty;
 59             }
 60 
 61             StringBuilder sb = new StringBuilder();
 62             if (!baselayer)
 63                 sb.Append("<div class=\"CheckboxTree\">");
 64 
 65             if (!isChildNode)
 66                 sb.Append("<ul class=\"CBT-ul\">");
 67             sb.Append("<li class=\"CBT-li\">");
 68 
 69             this_HtmlDomName = Name + "[" + Model.Index + "]";
 70 
 71             sb.Append("<label style=\"cursor:pointer;\">");
 72             sb.AppendFormat("<input type=\"checkbox\" onchange=\"setCheckboxTreeItemValue(this);\" name=\"{0}\" value=\"{1}\" />", (this_HtmlDomName + ".Checked"), Model.Checked.ToString());
 73             sb.AppendFormat("<span>{0}</span>", Model.Text);
 74             sb.Append("</label>");
 75 
 76             sb.AppendFormat("<input type=\"hidden\" name =\"{0}\" value=\"{1}\" />", (this_HtmlDomName + ".Text"), Model.Text);
 77             sb.AppendFormat("<input type=\"hidden\" name =\"{0}\" value=\"{1}\" />", (this_HtmlDomName + ".Value"), Model.Value);
 78             sb.AppendFormat("<input type=\"hidden\" name =\"{0}\" value=\"{1}\" />", (this_HtmlDomName + ".Index"), Model.Index);
 79 
 80             if (null != Model.Items)
 81             {
 82                 sb.Append("<ul class=\"CBT-ul\">");
 83                 for (var i = 0; i < Model.Items.Count; i++)
 84                 {
 85                     string _this_HtmlDomName;
 86                     sb.Append(CheckboxTree(helper, this_HtmlDomName + ".Items", Model.Items[i], out _this_HtmlDomName, true));
 87                 }
 88                 sb.Append("</ul>");
 89             }
 90 
 91             sb.Append("</li>");
 92             if (!isChildNode)
 93                 sb.Append("</ul>");
 94 
 95             if (!baselayer)
 96                 sb.Append("</div>");
 97 
 98             return sb.ToString();
 99         }
100         public static String CheckboxTree(this HtmlHelper helper, string Name, IList<CheckboxTreeItem> Models)
101         {
102             if (null == Models) return string.Empty;
103             if (Models.Count > 0)
104                 baselayer = true;
105 
106             StringBuilder sb = new StringBuilder();
107             if (baselayer)
108                 sb.Append("<div class=\"CheckboxTree\">");
109             sb.Append("<ul class=\"CBT-ul\">");
110 
111             string _this_HtmlDomName;
112 
113             foreach (CheckboxTreeItem item in Models)
114             {
115                 sb.Append(CheckboxTree(helper, Name, item, out _this_HtmlDomName, true));
116             }
117 
118             sb.Append("</ul>");
119             if (baselayer)
120                 sb.Append("</div>");
121 
122             return sb.ToString();
123         }
124     }
125 }

 

字段說明:
Text:用於顯示的文本,比如:總裁
Value:顯示文本對應的ID,比如:0
Index:這個是結合表單的輔助屬性,View上使用(注意每個層級的索引必需從0開始並且是連續的)
Checked:當前菜單項是否被選中,用戶提交表單后我們可以通過這個屬性判斷用戶的選擇項
Items:當前菜單下的子菜單集合

 

樹形菜單的輸出:

 1 @model List<CheckboxTreeItem>
 2 
 3 
 4 @using (Html.BeginForm("test", "Home", new { }, FormMethod.Post, new { id = "form", name = "form" }))
 5 {
 6   @Html.AntiForgeryToken();
 7     
 8   <link type="text/css" rel="stylesheet" href="@Url.Content("~/Models/CheckboxTree.css")" />
 9   @Html.Raw(Html.CheckboxTree("CheckboxTree", Model))   @*這里是輸出顯示樹形菜單*@
10   <script src="@Url.Content("~/Models/CheckboxTree.js")" type="text/javascript"></script>
11 }

 

       無論是ajax還是直接post表單,最終的目的都是接收View中的數據,要想傳遞比較復雜的數據類型,我們需要對ASP.NET MVC Model Binding 有一定了解,之前也講解過MyTreeViewItem的結果,有普通的數據類型,比如 string,bool,也是對象類型,比如MyTreeViewItem類型的Parent,也是基於集合的屬性IList<MyTreeViewItem>,要想讓表單中的數據直接傳遞給Controller,我們需要對表單元素的name進行特殊處理才行。

 

Controller:這是最重要的就是接收參數,它是一個List類型,無論菜單項有多少層,都會按樹形數據結構層次組織好,方便我們查詢。

 1 public ActionResult test(int id = 0)
 2 {
 3     ViewBag.IsEdit = id == 0 ? false : true;
 4 
 5     List<CheckboxTreeItem> cb = new List<CheckboxTreeItem>() {
 6             new CheckboxTreeItem() { Value="A", Text="一級A", Index="0" },
 7             new CheckboxTreeItem() { Value="B", Text="一級B", Index="1" },
 8             new CheckboxTreeItem() { Value="C", Text="一級C", Index="2", Checked =true,
 9             Items=new List<CheckboxTreeItem>() {
10                 new CheckboxTreeItem() { Value="CA", Text="二級CA", Index="0", Checked =true },
11                 new CheckboxTreeItem() { Value="CB", Text="二級CB", Index="1", Checked =true,
12                 Items=new List<CheckboxTreeItem>() {
13                     new CheckboxTreeItem() { Value="CBA", Text="三級CBA", Index="0", Checked =true },
14                     new CheckboxTreeItem() { Value="CBB", Text="三級CBB", Index="1", Checked =true },
15                     }
16                 },
17             }
18             },
19     };
20 
21     return View(cb);
22 }
23 
24 [HttpPost]
25 [ValidateAntiForgeryToken]
26 [ValidateInput(false)]
27 public ActionResult test(List<CheckboxTreeItem> CheckboxTree, int id = 0)
28 {
29     ViewBag.IsEdit = id == 0 ? false : true;
30 
31     return View(CheckboxTree);
32 }

下圖是Controller接收到的參數:(運行調試,斷點查看第27-31行代碼)

 

另外還有自定義樣式文件 CheckboxTree.css

 1 /*
 2 author:熊學浩
 3 time:2016年6月5日
 4 description:樹形菜單控件(有問題請致信:xiongzaiqiren@163.com),或者請參考【http://www.cnblogs.com/xiongzaiqiren/ 5 */
 6 /* CheckboxTree */
 7 .CheckboxTree {
 8     width: 100%;
 9     height: 100%;
10     text-align: center;
11     margin: 0 auto;
12 }
13 
14 .CBT-ul {
15     text-align: left;
16     list-style-type: disc;
17 }
18 
19     .CBT-ul .CBT-li {
20         display: list-item;
21         text-align: left;
22         margin-left: 10px;
23         font-size: 16px;
24         line-height: 20px;
25         word-wrap: break-word;
26         word-break: nomal;
27         list-style: inherit;
28     }
29 .CBT-li label {
30     cursor: pointer;
31 }
32 .CBT-li label input[type="checkbox"] {
33     width: 16px;
34     height: 16px;
35     padding: 0 5px 0 0;
36 }
37 
38 .CBT-li span {
39     
40 }
41 
42     .CBT-li a:link, .CBT-li a:visited {
43     }
44 
45     .CBT-li a:hover, .CBT-li a:active {
46         color: #ffffff;
47         background-color: #657386;
48     }
49 
50     .CBT-li a.active {
51         color: #ffffff;
52         background-color: #657386;
53     }
54 
55     .CBT-li a span {
56         
57     }
CheckboxTree.css

用於初始化和設置選擇狀態改變的自定義javascript文件 CheckboxTree.js

 1 /*
 2 author:熊學浩
 3 time:2016年6月5日
 4 description:樹形菜單控件(有問題請致信:xiongzaiqiren@163.com),或者請參考【http://www.cnblogs.com/xiongzaiqiren/ 5 */
 6 /* CheckboxTree */
 7 function setCheckboxTreeItemValue(dom) {
 8     try {
 9         if (!!dom)
10             dom.value = (!!dom.checked)
11     }
12     catch (e) {
13         console.log(e.message);
14     }
15 };
16 function iniCheckboxTree() {
17     try {
18         var cbList = document.getElementsByTagName("input");
19         if (!!cbList && cbList.length > 0) {
20             for (var i = 0; i < cbList.length; i++) {
21                 if (!!cbList[i] && (cbList[i].type == "checkbox")) {
22                     if (!!cbList[i].value) {
23                         cbList[i].checked = (cbList[i].value.toLowerCase() == "true") || false;
24                     }
25                 }
26             }
27         }
28     }
29     catch (e) {
30         console.log(e.message);
31     }
32 };
33 
34 if (!!window)
35     window.onload = iniCheckboxTree();
36 else
37     iniCheckboxTree();
CheckboxTree.js

最后,UI效果圖:

【完】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM