不再为无限级树结构烦恼,且看此篇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 = "&nbsp;";
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 }
View Code
  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>
View Code

示例:

使用原数据:

生成HTML中,每一级每一条都包含在使用相同class的DIV当中,不同之外在于自定义的level,parent,rel等属性,请参见代码.

 

下列为调用代码方法,各参数可自行设定,说见用户控件CS代码:

 

由于时间问题,可能很多地方不便细说.如有更多疑问,请加QQ群:ASP.NET高级群,群号: 261882616

 

 

 

posted @ 2013-07-31 10:39  历史的驱动  阅读(1125)  评论(12编辑  收藏  举报