最近項目中有一個需求,將樹形結構的數據,以表格的形式展示在頁面中,下圖是最終呈現效果: 源碼: 後臺代碼: 全部源碼:Asp.Net Mvc自定義控制項之樹形結構數據生成表格-WPF特工隊內部資料.rar ...
最近項目中有一個需求,將樹形結構的數據,以表格的形式展示在頁面中,下圖是最終呈現效果:
源碼:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Asp.Net Mvc自定義控制項之樹形結構數據生成表格 - WPF特工隊內部資料</title>
<style type="text/css"> table.hovertable { font-family: verdana, arial, sans-serif; font-size: 11px; color: #333333; border-width: 1px; border-color: #999999; border-collapse: collapse; } table.hovertable th { background-color: #c3dde0; border-width: 1px; padding: 8px; border-style: solid; border-color: #a9c6c9; } table.hovertable tr { background-color: #d4e3e5; } table.hovertable td { border-width: 1px; padding: 8px; border-style: solid; border-color: #a9c6c9; text-align: center; } table.hovertable td.td-left { text-align: left; } </style> </head> <body> @Html.TabTree(ViewData["Source"] as List<V_TabTree>, @classname: "hovertable") </body> </html>
後臺代碼:
namespace FLSoft.WebUI { public class Data { /// <summary> /// 構建數據源 /// </summary> /// <returns></returns> public static List<V_TabTree> GetData() { List<V_TabTree> _datas = new List<V_TabTree>(); // #region 深度測試 var 深度測試 = new V_TabTree("測試1", 5) { Childs = new List<V_TabTree>() { new V_TabTree("測試1-1",4){ Childs = new List<V_TabTree>(){ new V_TabTree("測試1-1-1",2){ Childs =new List<V_TabTree>(){ new V_TabTree("測試1-1-1-1"), new V_TabTree("測試1-1-1-2") } }, new V_TabTree("測試1-1-2",2){ Childs =new List<V_TabTree>(){ new V_TabTree("測試1-1-2-1"), new V_TabTree("測試1-1-2-2") } } } }, new V_TabTree("測試1-2",1){ Childs = new List<V_TabTree>(){ new V_TabTree("測試1-2-1",1){ Childs =new List<V_TabTree>(){ new V_TabTree("測試1-2-1-1") } } } } } }; #endregion #region 高壓配電櫃 var 高壓配電櫃 = new V_TabTree("高壓配電櫃", 4) { Childs = new List<V_TabTree>() { new V_TabTree("真空斷路器",1){ Childs = new List<V_TabTree>(){ new V_TabTree("固定牢固無鬆動,外表清潔完好,分合閘無異常") } }, new V_TabTree("“五防”功能",1){ Childs = new List<V_TabTree>(){ new V_TabTree("工作正常") } }, new V_TabTree("接線端子",1){ Childs = new List<V_TabTree>(){ new V_TabTree("無燒毀或鬆動") } }, new V_TabTree("微機綜保",1){ Childs = new List<V_TabTree>(){ new V_TabTree("上下級聯動協調") } } } }; #endregion #region 閥門 var 閥門 = new V_TabTree("閥門", 4) { Childs = new List<V_TabTree>() { new V_TabTree("閥門保養",3){ Childs = new List<V_TabTree>(){ new V_TabTree("檢查各零件部件的腐蝕、磨損程度,發現損壞則更換或整修"), new V_TabTree("清除垃圾油污,並加註潤滑脂1"), new V_TabTree("清除垃圾油污,並加註潤滑脂2") } }, new V_TabTree("計量儀錶",1){ Childs = new List<V_TabTree>(){ new V_TabTree("計量準確") } } } }; #endregion #region 閥門2 var 閥門2 = new V_TabTree("閥門2", 2) { Childs = new List<V_TabTree>() { new V_TabTree("閥門保養",2){ Childs = new List<V_TabTree>(){ new V_TabTree("檢查各零件部件的腐蝕、磨損程度,發現損壞則更換或整修"), new V_TabTree("清除垃圾油污,並加註潤滑脂") } } } }; #endregion #region 電容器櫃 var 電容器櫃 = new V_TabTree("電容器櫃", 3) { Childs = new List<V_TabTree>() { new V_TabTree("電力電容",1){ Childs = new List<V_TabTree>(){ new V_TabTree("無漏油、過熱、膨脹現象,絕緣正常") } }, new V_TabTree("接觸器",1){ Childs = new List<V_TabTree>(){ new V_TabTree("觸頭無燒損痕跡、閉合緊密") } }, new V_TabTree("熔斷器",1){ Childs = new List<V_TabTree>(){ new V_TabTree("無燒損痕跡") } } } }; #endregion _datas.Add(深度測試); _datas.Add(高壓配電櫃); _datas.Add(閥門); _datas.Add(閥門2); _datas.Add(電容器櫃); return _datas; } } /// <summary> /// 表格樹數據模型 /// </summary> public class V_TabTree { #region 構造函數 public V_TabTree() { this.Depth = 0; this.Childs = new List<V_TabTree>(); } public V_TabTree(String value) : this() { this.Value = value; } public V_TabTree(String value, Int32 depth) : this(value) { this.Depth = depth; } #endregion /// <summary> /// 主鍵 /// </summary> public Int32 ID { get; set; } /// <summary> /// 所屬父節點 /// </summary> public Int32 ParentID { get; set; } /// <summary> /// 節點內容 /// </summary> public String Value { get; set; } /// <summary> /// 子位元組 /// </summary> public List<V_TabTree> Childs { get; set; } /// <summary> /// 節點深度 /// </summary> public Int32 Depth { get; private set; } /// <summary> /// 節點是否已生成 /// </summary> public Boolean IsGenerate { get; set; } /// <summary> /// 添加子節點 /// </summary> /// <param name="node"></param> public virtual void Addchildren(V_TabTree node) { this.Childs.Add(node); } /// <summary> /// 獲取當前節點的深度 /// 參考: /// --| 菜單1 /// ----|菜單1.1 /// ------|菜單1.1.1 /// ------|菜單1.1.2 /// ----|菜單1.2 /// ------|菜單1.2.1 /// ------|菜單1.2.2 /// 如上是一個三級節點,但是頂級節點的深度為4,表示這個菜單1的所有子節點總和 /// </summary> /// <returns></returns> public virtual Int32 GetDepth() { Int32 _depth = 0; //獲取當前節點的深度 if (this.Childs.Count > 1) { } return _depth; } } /// <summary> /// 創建HTML Table數據模型 /// </summary> public class V_Tab { public V_Tab() { this.Ths = new List<V_Tr>(); this.Trs = new List<V_Tr>(); } /// <summary> /// 表格標題 /// </summary> public List<V_Tr> Ths { get; set; } /// <summary> /// 表格內容 /// </summary> public List<V_Tr> Trs { get; set; } } /// <summary> /// 創建HTML Table 列數據模型 /// </summary> public class V_Td { public V_Td() { this.Colspan = 1; this.Rowspan = 1; } /// <summary> /// 顯示內容 /// </summary> public String Value { get; set; } /// <summary> /// 標題合併列數 /// </summary> public Int32 Colspan { get; set; } /// <summary> /// 標題合併行數 /// </summary> public Int32 Rowspan { get; set; } } /// <summary> /// 創建HTML Table行數據模型 /// </summary> public class V_Tr { public V_Tr() { this.Tds = new List<V_Td>(); } /// <summary> /// 行樣式名稱 /// </summary> public String ClassName { get; set; } /// <summary> /// 列數據集合 /// </summary> public List<V_Td> Tds { get; set; } } /// <summary> /// TabTree 自定義控制項 /// </summary> public static class MvcHtmlStringExtensions { /// <summary> /// 構建表格 /// </summary> /// <param name="helper"></param> /// <returns></returns> public static MvcHtmlString TabTree(this HtmlHelper helper, V_Tab values, String classname) { StringBuilder htmlStr = new StringBuilder(); if (values == null) return new MvcHtmlString("<TABLE></TABLE>"); htmlStr.Append("<TABLE class= " + classname + ">"); if (values.Ths != null) { foreach (var th in values.Ths) { htmlStr.Append("<TR>"); if (th.Tds != null) { foreach (var td in th.Tds) { htmlStr.Append("<TH colspan =" + td.Colspan + " rowspan =" + td.Rowspan + " >"); htmlStr.Append(td.Value + "</TH>"); } } htmlStr.Append("</TR>"); } } if (values.Trs != null) { foreach (var tr in values.Trs) { htmlStr.Append("<TR>"); if (tr.Tds != null) { foreach (var td in tr.Tds) { htmlStr.Append("<TD colspan =" + td.Colspan + " rowspan =" + td.Rowspan + " >"); htmlStr.Append(td.Value + "</TD>"); } } htmlStr.Append("</TR>"); } } htmlStr.Append("</TABLE>"); return new MvcHtmlString(htmlStr.ToString()); } /// <summary> /// 構建表格 /// </summary> /// <param name="helper"></param> /// <param name="tab"></param> /// <returns></returns> public static MvcHtmlString TabTree(this HtmlHelper helper, List<V_TabTree> source, String classname) { StringBuilder htmlStr = new StringBuilder(); V_Tab _tab = new V_Tab(); _tab.Trs = BuildTr(source); return TabTree(helper, _tab, classname); } /// <summary> /// 將樹形的數據構建為HTML Table數據模型 /// </summary> /// <param name="values"></param> /// <returns></returns> private static List<V_Tr> BuildTr(List<V_TabTree> values) { List<V_Tr> _trs = new List<V_Tr>(); foreach (var value in values) { _trs.AddRange(GenerateTr(value)); //一個頂級節點的行數由value.Depth屬性來確定 } return _trs; } /// <summary> /// 僅滿足1級節點合併 /// </summary> /// <param name="value"></param> /// <returns></returns> private static List<V_Tr> BuildTr(V_TabTree value) { List<V_Tr> _trs = new List<V_Tr>(); //Depth屬性用於判斷當前的數據產生Tr的數量 for (int i = 0; i < value.Depth; i++) { V_Tr _tr = new V_Tr(); if (i == 0) { V_Td _td = new V_Td() { Value = value.Value, Rowspan = value.Depth }; _tr.Tds.Add(_td); } //檢測是否包含子節點,如果包含 if (value.Childs != null && value.Childs.Count > 0) { //頂級節點的深度與其子節點數目相等時,後續表格的列都是一對一的 if (value.Depth == value.Childs.Count) { _tr.Tds.AddRange(BuildTd(value.Childs[i])); } else //如果幾點深度大於子節點時,需要計算迴圈深度 { //父節點的級別與所有子節點的深度總和相等 } } _trs.Add(_tr); } return _trs; } /// <summary> /// 僅滿足1-2級節點合併 /// </summary> /// <param name="parentNode"></param> /// <returns></returns> private static List<V_Tr> BuildTrEx(V_TabTree parentNode) { List<V_Tr> _trs = new List<V_Tr>(); V_Tr _tr = new V_Tr(); //當包含一個數據節點時,創建第一個TR _tr.Tds = BuildTd(parentNode); //填充TR包含的所有的TD _trs.Add(_tr); //填充TR集合 if (parentNode.Depth > 1) //判斷Depth>1表示這個節點下麵還包含TR行 { if (parentNode.Childs.Count > 1) //如果當前節點包含多個子節點,需要迴圈遍歷 { //後續描述的"當前節點",是當前For迴圈上下文的節點,不是指的參數節點 var _childNodes = parentNode.Childs; for (int i = 0; i < _childNodes.Count; i++) //在迴圈子節點時,子節點的第一個項已經賦值給Parent節點了 { //所以只處理Depth>1的業務,parentNode的子節點(childNodes)還包含可以迴圈子節點 if (_childNodes[i].Depth > 1) //表示當前這個節點後續的TR行包含多個 { //繼續迴圈當前節點的子節點(頂級節點的子節點的子節點判斷,有點繞) for (int ii = 0; ii < _childNodes[i].Childs.Count; ii++) { if (ii > 0) { //因為是當前節點的二級節點,那麼第一條數據被上父節點給取走了,迴圈就需要從i+1開始 _trs.AddRange(BuildTrEx(_childNodes[i].Childs[ii])); } } } else //如果當前節點的Depth =1 ,表示這個節點已經被賦值給Parent節點了, { if (i > 0) { _trs.AddRange(BuildTrEx(_childNodes[i])); //取子節點遞歸查找 } } } } else //二級節點只有一項時 { for (int i = 0; i < parentNode.Childs[0].Childs.Count - 1; i++) { _trs.AddRange(BuildTrEx(parentNode.Childs[0].Childs[i + 1])); } } } return _trs; } /// <summary> /// 多級節點嵌套合併 /// </summary> /// <param name="parentNode">父節點</param> /// <returns></returns> private static List<V_Tr> GenerateTr(V_TabTree parentNode) { List<V_Tr> _trs = new List<V_Tr>(); if (!parentNode.IsGenerate) { V_Tr _tr = new V_Tr(); _tr.Tds = BuildTd(parentNode); _trs.Add(_tr); } if (parentNode.Depth > 1) //有多級深度 { //檢測其子節點是否包含深度,肯定是要添加一個迴圈遍歷的 List<V_TabTree> childNodes = parentNode.Childs; for (int i = 0; i < childNodes.Count; i++) { _trs.AddRange(GenerateTr(childNodes[i])); } } return _trs; } private static List<V_Td> BuildTd(V_TabTree value) { List<V_Td> _tds = new List<V_Td>(); value.IsGenerate = true; V_Td _td = new V_Td() { Value = value.Value, Rowspan = value.Depth > 0 ? value.Depth : 1 }; _tds.Add(_td); if (value.Depth > 0) { _tds.AddRange(BuildTd(value.Childs[0])); } return _tds; } } }
全部源碼:Asp.Net Mvc自定義控制項之樹形結構數據生成表格-WPF特工隊內部資料.rar