不再为无限级树结构烦恼,且看此篇s
很久都没有写点什么出来分享了,最近在做多级树的时候,发现来来回回写过很多遍,于是封装成用户控件,以方便日后重复使用.
首先上效果:
我们看到以上2种效果,都是支持任意级的,这里源码中使用的是递归,以便高效的完成HTML的渲染.
下面上代码,代码中解释的都很详细了,我就不再细说.下面将有示例调用演示:
1 public partial class UC_MultiLevelTree : System.Web.UI.UserControl 2 { 3 #region 数据相关属性 4 5 /// <summary> 6 /// 要绑定的数据源 7 /// </summary> 8 public DataTable DataSource { get; set; } 9 10 /// <summary> 11 /// 多级树显示文本所在列列名 12 /// </summary> 13 public string TextFeild { get; set; } 14 15 /// <summary> 16 /// 多级树单条数据识别列列名(即选择项的值) 17 /// </summary> 18 public string ValueFeild { get; set; } 19 20 /// <summary> 21 /// 多级树层级区别列列名(仅限单个列区分层级) 22 /// </summary> 23 public string LevelFeild { get; set; } 24 25 /// <summary> 26 /// 多级树顶级的父项值 27 /// </summary> 28 public string TopLevelFeildValue { get; set; } 29 30 #endregion 31 32 #region 显示相关属性 33 34 /// <summary> 35 /// 是否显示多选框,默认为显示 36 /// </summary> 37 public bool ShowCheckBox { get; set; } 38 39 /// <summary> 40 /// 是否显示自定义根节点 41 /// </summary> 42 public bool ShowCustomerRoot { get; set; } 43 44 /// <summary> 45 /// 自定义根节点文本 46 /// </summary> 47 public string CustomerRootText { get; set; } 48 49 /// <summary> 50 /// 多级树宽度,可为像素或者百分比 51 /// </summary> 52 public string Width { get; set; } 53 54 /// <summary> 55 /// 多级树高度,可为像素或者百分比 56 /// </summary> 57 public string Height { get; set; } 58 59 /// <summary> 60 /// 展开符号(可为HTML代码) 61 /// </summary> 62 public string ExtendSign { get; set; } 63 64 /// <summary> 65 /// 收缩符号(可为HTML代码) 66 /// </summary> 67 public string ShrinkSign { get; set; } 68 69 /// <summary> 70 /// 每级与上级空格个数 71 /// </summary> 72 public int LevelSeparatorCount { get; set; } 73 74 /// <summary> 75 /// 默认展开级别 76 /// </summary> 77 public int ExtendLevelNum { get; set; } 78 79 #endregion 80 81 #region 私有变量 82 83 /// <summary> 84 /// 扩展标记的HTML 85 /// </summary> 86 private string StrExtendSign; 87 88 /// <summary> 89 /// 收缩标记的HTML 90 /// </summary> 91 private string StrShrinkSign; 92 93 /// <summary> 94 /// 多选框的HTML 95 /// </summary> 96 private string StrCheckbox; 97 98 /// <summary> 99 /// 子层级开始符号的HTML 100 /// </summary> 101 private string LevelSeparator = " "; 102 103 #endregion 104 105 106 protected override void OnInit(EventArgs e) 107 { 108 base.OnInit(e); 109 this.ShowCheckBox = true; 110 this.Width = "100%"; 111 this.Height = "100%"; 112 this.ExtendSign = "[+]"; 113 this.ShrinkSign = "[-]"; 114 this.TopLevelFeildValue = CRMCommon.strNullGuid; 115 this.LevelSeparatorCount = 4; 116 this.ExtendLevelNum = 2; 117 } 118 119 120 protected void Page_Load(object sender, EventArgs e) 121 { 122 123 } 124 125 public void DataBind() 126 { 127 this.StrCheckbox = this.ShowCheckBox ? "<input type='checkbox' class='MLT_Checkbox'/>" : ""; 128 this.StrExtendSign = "<span class='MLT_ExtendSign' {0}>" + this.ExtendSign + "</span>"; 129 this.StrShrinkSign = "<span class='MLT_ShrinkSign' {0}>" + this.ShrinkSign + "</span>"; 130 this.ltMultiLevelTreeHtml.Text = RenderTree(this.TopLevelFeildValue, 1); 131 } 132 133 134 private string RenderTree(string parentValue, int level) 135 { 136 StringBuilder sb = new StringBuilder(); 137 138 string extendSignHtml = ""; 139 string shrinkSignHtml = ""; 140 141 //收缩,展开按钮的显示控制 142 if (level < this.ExtendLevelNum) 143 { 144 extendSignHtml = string.Format(this.StrExtendSign, "style='display:none;'"); 145 shrinkSignHtml = string.Format(this.StrShrinkSign, ""); 146 } 147 else 148 { 149 extendSignHtml = string.Format(this.StrExtendSign, ""); 150 shrinkSignHtml = string.Format(this.StrShrinkSign, "style='display:none;'"); 151 } 152 153 //自定义根节点 154 if (level == 1) 155 { 156 sb.AppendFormat("<div class='MLT_Panel' style='width:{0};height:{1}'>", this.Width, this.Height); 157 if (this.ShowCustomerRoot) 158 { 159 sb.AppendFormat("<div class='MLT_Item' level='{0}' rel=''>{1}<span class='MLT_Item_Text'>{2}</span></div>", level, extendSignHtml + shrinkSignHtml + this.StrCheckbox, this.CustomerRootText); 160 161 level += 1; 162 } 163 sb.Append(RenderTree(parentValue, level)); 164 sb.Append("</div>"); 165 } 166 167 else if (level != 1) 168 { 169 //数据项绑定 170 if (this.DataSource != null && this.DataSource.Rows.Count > 0) 171 { 172 string levelSeparator = ""; 173 174 if (level > 1) 175 { 176 levelSeparator += "<span class='MLT_LevelSeparator'>"; 177 for (int i = 1; i <= (level - 1) * this.LevelSeparatorCount; i++) 178 { 179 levelSeparator += this.LevelSeparator; 180 } 181 levelSeparator += "</span>"; 182 } 183 184 DataRow[] drList = this.DataSource.Select(string.Format("{0}='{1}'", this.LevelFeild, parentValue)); 185 186 if (drList != null && drList.Length > 0) 187 { 188 level += 1; 189 foreach (DataRow dr in drList) 190 { 191 string childHtml = RenderTree(dr[ValueFeild].ToString(), level); 192 193 string signs = string.IsNullOrWhiteSpace(childHtml) ? "<span class='MLT_ExtendSignPlaceholder'></span>" : extendSignHtml + shrinkSignHtml; 194 195 sb.AppendFormat("<div class='MLT_Item' level='{0}' rel='{1}' parent='{2}' {3}>{4}<span class='MLT_Item_Text'>{5}</span></div>", level - 1, dr[ValueFeild], dr[LevelFeild], level - 1 > this.ExtendLevelNum ? "style='display:none;'" : "", levelSeparator + signs + this.StrCheckbox, dr[TextFeild]); 196 197 if (!string.IsNullOrWhiteSpace(childHtml)) 198 { 199 sb.Append(childHtml); 200 } 201 } 202 } 203 } 204 } 205 return sb.ToString(); 206 207 } 208 }
1 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="UC_MultiLevelTree.ascx.cs" Inherits="UC_MultiLevelTree" %> 2 <asp:Literal runat="server" ID="ltMultiLevelTreeHtml"></asp:Literal> 3 <script> 4 $(function () { 5 $(".MLT_Item").click(function (e) { 6 e.stopPropagation(); 7 $(".MLT_Item").removeClass("MLT_Item_hover"); 8 $(this).addClass("MLT_Item_hover"); 9 extendItem(this); 10 }); 11 12 $(".MLT_ExtendSign").click(function (e) { 13 e.stopPropagation(); 14 var event = e.currentTarget; 15 var item = $(event).parent(); 16 extendItem(item); 17 }) 18 19 $(".MLT_ShrinkSign").click(function (e) { 20 e.stopPropagation(); 21 var event = e.currentTarget; 22 var item = $(event).parent(); 23 shrinkItem(item); 24 }) 25 26 $(".MLT_Checkbox").click(function (e) { 27 e.stopPropagation(); 28 var event = e.currentTarget; 29 var item = $(event).parent(); 30 var checked = $(event).attr("checked"); 31 checkItems(item, checked); 32 }); 33 }); 34 35 //展开项 36 function extendItem(obj) { 37 var rel = $(obj).attr("rel"); 38 if (rel != undefined && rel.length > 0) { 39 $(obj).siblings("div[parent=" + rel + "]").each(function () { 40 $(this).show(); 41 }); 42 } 43 else { 44 $(obj).siblings("div[level=2]").show(); 45 } 46 $(obj).find(".MLT_ExtendSign").hide(); 47 $(obj).find(".MLT_ShrinkSign").show(); 48 } 49 50 //收缩项 51 function shrinkItem(obj) { 52 var rel = $(obj).attr("rel"); 53 if (rel != undefined && rel.length > 0) { 54 $(obj).siblings("div[parent=" + rel + "]").each(function () { 55 $(this).hide(); 56 $(this).find(".MLT_ExtendSign").show(); 57 $(this).find(".MLT_ShrinkSign").hide(); 58 shrinkItem(this); 59 }); 60 } 61 else { 62 $(obj).siblings("div[level!=1]").hide(); 63 $(obj).siblings("div[level!=1]").find(".MLT_ExtendSign").show(); 64 $(obj).siblings("div[level!=1]").find(".MLT_ShrinkSign").hide(); 65 } 66 $(obj).find(".MLT_ExtendSign").show(); 67 $(obj).find(".MLT_ShrinkSign").hide(); 68 } 69 70 //选择项 71 function checkItems(obj, checked) { 72 var rel = $(obj).attr("rel"); 73 if (rel != undefined && rel.length > 0) { 74 if (checked) { 75 $(obj).siblings("div[parent=" + rel + "]").each(function () { 76 $(this).find("input[type=checkbox]").attr("checked", "checked"); 77 checkItems(this, checked); 78 }); 79 } 80 else { 81 $(obj).siblings("div[parent=" + rel + "]").each(function () { 82 $(this).find("input[type=checkbox]").removeAttr("checked"); 83 checkItems(this, checked); 84 }); 85 } 86 } 87 else { 88 if (checked) { 89 $(obj).parent().find("input[type=checkbox]").attr("checked", "checked"); 90 } 91 else { 92 $(obj).parent().find("input[type=checkbox]").removeAttr("checked"); 93 } 94 } 95 } 96 </script> 97 <style type="text/css"> 98 .MLT_Panel 99 { 100 white-space: nowrap; 101 overflow: auto; 102 } 103 104 .MLT_Item 105 { 106 font-size: 12px; 107 line-height: 20px; 108 cursor: pointer; 109 } 110 111 .MLT_Item_hover 112 { 113 background-color: rgb(167, 205, 240); 114 } 115 116 .MLT_Item span 117 { 118 line-height: 20px; 119 display: inline-block; 120 } 121 122 .MLT_Checkbox 123 { 124 position: relative; 125 width: 12px; 126 height: 12px; 127 margin: 0 2px; 128 bottom: 2px; 129 } 130 131 .MLT_ExtendSign, .MLT_ShrinkSign, .MLT_ExtendSignPlaceholder 132 { 133 font-family: "宋体"; 134 width: 18px; 135 text-align: center; 136 } 137 </style>
示例:
使用原数据:
生成HTML中,每一级每一条都包含在使用相同class的DIV当中,不同之外在于自定义的level,parent,rel等属性,请参见代码.
下列为调用代码方法,各参数可自行设定,说见用户控件CS代码:
由于时间问题,可能很多地方不便细说.如有更多疑问,请加QQ群:ASP.NET高级群,群号: 261882616