简单但完整的树形列表+多选(复选)框实现方式
2010-07-09 01:25 watsonchia 阅读(4238) 评论(0) 编辑 收藏 举报多级分类通常做成树形的,如果分类是单选的,只要递归返回树形结构,用下拉列表显示就ok了。当分类要求多选的时候,我们需要给每个分类都加上复选框。在Asp.Net里TreeView可以显而易见的做到这个,然而TreeView服务端控件不但生成比较ugly的html代码,而且所需写代码的时候其实也并不是最少。下面给出我的一个简单(代码数较少)但是完整的实现方式,除了显示,还包括取得选中值以及对树形列表赋值 。需要达到的效果如下,点击一个span可展开或收起树形列表。
我选择用ul显示树形列表,这也是一个常用的方式。下面是aspx页面的代码,用jquery编写相关的脚本。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <style type="text/css"> body { font-size: 12px; font-family: Verdana, 微软雅黑; } ul { margin: 0px 10px; padding: 0px 10px; list-style: none; } li { line-height: 16px; } </style> <script src="Scripts/jquery.js" type="text/javascript"></script> <script type="text/javascript"> //选中itemList里的保存Id的Checkbox function checkItems(nodeName, itemList) { var arr = itemList.split(','); $.each(arr, function (i, n) { $("#" + nodeName + "-" + arr[i]).attr("checked", "checked"); }); } $(function () { //点击展开或收起树形列表 $("#spCategory").click(function (event) { event.stopPropagation(); var offset = $(this).offset(); $('#ulCategory').css({ left: offset.left, top: offset.top + 30 }).toggle(); }); //取消弹出层本身冒泡事件 $("#ulCategory").click(function (event) { event.stopPropagation(); }); //点击页面其他位置使弹出层消失 $(document).click(function () { $("#ulCategory").hide(); }); }); </script> </head> <body> <span id="spCategory" style="border: solid 1px silver; line-height: 25px; padding: 3px 5px; cursor: pointer; float: left;">点击这里展开或收起分类</span> <ul id="ulCategory" style="position: absolute; background-color: ActiveCaption; display: none;"> <asp:Literal ID="ltrCategory" runat="server"></asp:Literal> </ul> </body> </html>
后台cs代码如下,主要是返回树形结构。
public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { DataSet ds = new DataSet(); ds.ReadXml(Server.MapPath("Category.xml")); ltrCategory.Text = GetTreeHtml(ds.Tables[0], "category"); } string GetTreeHtml(DataTable dt, string nodeName) { StringBuilder sb = new StringBuilder(); DataView dv = new DataView(dt); dv.RowFilter = "ParentId = 0"; foreach (DataRowView rv in dv) { sb.Append("<li>"); sb.AppendFormat("<label><input type='checkbox' id='{0}-{1}' name='{0}' value='{1}' />{2}</label>", nodeName, rv["Id"], rv["Name"]); AddChild(sb, dt, rv, nodeName); sb.Append("</li>"); } return sb.ToString(); } void AddChild(StringBuilder sb, DataTable dt, DataRowView drv, string nodeName) { DataView dv = new DataView(dt); dv.RowFilter = string.Format("ParentId = {0}", drv["Id"]); if (dv.Count > 0) sb.Append("<ul>"); else return; foreach (DataRowView rv in dv) { sb.Append("<li>"); sb.AppendFormat("<label><input type='checkbox' id='{0}-{1}' name='{0}' value='{1}' />{2}</label>", nodeName, rv["Id"], rv["Name"]); AddChild(sb, dt, rv, nodeName); sb.Append("</li>"); } sb.Append("</ul>"); } }
代码里返回树形html的方法是GetTreeHtml,两个参数,分别是保持分类信息的datatable,以及checkbox的name。如上代码里,checkbox的name为category,则提交到后台时可以使用
Request.Form["category"]
取得选中值,而且是已序列化好的。比如选中了Id为1,2,3的三个分类的checkbox,则取得值为:1,2,3。而把这个序列赋值到树形列表上,只要简单的调用aspx里的一个js函数checkItems(nodeName, itemList),如
checkItems('category', '1,2,3')
相比TreeView服务端控件,不但生成的html更干净,而且所写总的代码行数也更少,当然js代码行数少是因为使用jquery的缘故 -)
以上demo代码里使用xml保存多级分类数据,包括三个字段,分类Id、父类Id,分类名称,如下
<?xml version="1.0" encoding="utf-8" ?> <Categories> <Category Id="1" ParentId="0" Name="首页"></Category> <Category Id="2" ParentId="1" Name="政策法规"></Category> <Category Id="3" ParentId="1" Name="行政公告"></Category> <Category Id="4" ParentId="0" Name="新闻中心"></Category> <Category Id="5" ParentId="2" Name="政策"></Category> <Category Id="6" ParentId="2" Name="法规"></Category> </Categories>