Asp.Net Mvc自定義控件之樹形結構數據生成表格 - WPF特工隊內部資料

  最近項目中有一個需求,將樹形結構的數據,以表格的形式展現在頁面中,下圖是最終呈現效果:css

  

 

 

   源碼:html

  

@{
    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>

 

後臺代碼:node

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函數

相關文章
相關標籤/搜索