为了满足在一个树形菜单上添加多级子菜单,我们想到用递归来实现,这样做,灵活度立马提升!不管用户想添加多少级菜单我们都能满足他!但是如果考虑到性能的话,递归可能会影响到性能,所以说用的时候还是需要多方面考虑的。
先根据数据库表介绍一下我们的实现逻辑,以下是使用到的数据库表
TR_Resource
ID ResourceName ParentID 1 廊坊师范学院 0 2 数信学院 1 3 物电学院 1 4 信息与计算科学专业 2
ID:ParentID 对应的子节点id
ResourceName:名称
ParentID:父节点id,即当ParentID的值与ID的值相等时,他们才为父子的关系,如廊坊师范学院的ID为“1”,而数信学院和物电学院的ParentID的值也为“1”,那么证明数信学院和物电学院都为廊坊师范学院的孩子节点,又如:数信学院的ID为“2”,而信息与计算科学的ParentID也为“2”,证明信息与计算科学是数信学院的孩子节点。
这次学习zTree还学习到了一点,就是在js方法中直接调用后台的方法,不过后台方法前边需要添加[WebMethod],方法还得是static的,这一点我也不是很清楚,如果我哪里说得不对的地方麻烦大侠帮忙指出来,下面就来介绍一下我的实现过程。
js
<head runat="server"> <title></title> <link href="Styles/zTreeStyle/zTreeStyle.css" rel="stylesheet" type="text/css" /> <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> <script src="Scripts/jquery.ztree.core-3.5.js" type="text/javascript"></script> <script type="text/javascript"> function showIconForTree(treeId, treeNode) { return !treeNode.isParent; }; function zTreeOnClick(event, treeId, treeNode) { //获取地址 var url=treeNode.cUrl; //打开链接 open(url); //用于框架中 //open(url, "_parent", true); } var setting = { callback: { onClick: zTreeOnClick }, view: { showIcon: showIconForTree }, data: { key: { children: "children", name: "cName", title: "", url: "URL" }, simpleData: { enable: true } } }; $(document).ready(function () { $.ajax({ type: "post", contentType: "application/json", url: "Index.aspx/FindAll", data: "{}", dataType: "json", success: function (result) { var zNodes = result.d; //接受webservice里面传过来的list //创建ztree $.fn.zTree.init($("#treeDemo"), setting, zNodes); } }); }); </script> </head> <body> <form id="form1" runat="server"> <div> <ul id="treeDemo" class="ztree"> </ul> </div> </form> </body>
后台using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Web.Services; using System.Data.SqlClient; using System.Configuration; using System.Text; namespace WebForzTree { public partial class Index : System.Web.UI.Page { private static string connectionString = ConfigurationManager.ConnectionStrings["DBConnString"].ToString(); public string NodeData; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { } } //XML里面的一个方法,在jquery用ajax方法调用; /// <summary> /// 获取所有的一级节点 /// </summary> /// <returns>所有的节点信息</returns> [WebMethod] public static List<dCategory> FindAll() { //实例化类 Index index = new Index(); SqlConnection connection = new SqlConnection(connectionString); string sqlText = "select * from TR_Resource where ParentID=0"; //定义实体类列表 List<dCategory> list = new List<dCategory>(); //将所有的一级节点放到list中 list =index.GetParentID(sqlText); index.GetChilds(ref list); return list; } /// <summary> ///获所有的一级节点 /// </summary> /// <param name="sql"></param> /// <returns></returns> private List<dCategory> GetParentID(string sql) { List<dCategory> user = new List<dCategory>(); SqlDataReader reader = null; reader = ExecuteReader(sql); while (reader.Read()) { user.Add(ObjToListC(reader)); } return user; } /// <summary> /// 将获取的所有的子节点放到children中 /// </summary> /// <param name="list">按引用传值,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中</param> public void GetChilds(ref List<dCategory> list) { foreach (dCategory model in list) { //通过上级ID获取子级,然后添加到lstModel中 List<dCategory> lstModel = GetChildsID(model.cId); if (lstModel.Count > 0) { model.children = lstModel; //采用递归的形式 GetChilds(ref lstModel); } } } /// <summary> /// 根据父节点的id获取子节点 /// </summary> /// <param name="dParentId">父节点id</param> /// <returns>所有的子节点id</returns> public List<dCategory> GetChildsID(string dParentId) { //定义一个列 List<dCategory> result = new List<dCategory>(); SqlDataReader sqlReader = null; string strSql = String.Format(@"select * from TR_Resource where ParentID={0}", dParentId); sqlReader = ExecuteReader(strSql); while (sqlReader.Read()) { result.Add(ObjToListC(sqlReader)); } sqlReader.Close(); return result; } /// <summary> /// 解析查询结果 /// </summary> /// <param name="reader"></param> /// <returns>父节点id,子节点id,子节点名字</returns> private dCategory ObjToListC(SqlDataReader reader) { dCategory model = new dCategory(); if (reader != null) { //子节点id if (reader["ID"] != null && reader["ID"].ToString() != "") { model.cId = reader["ID"].ToString(); } //节点名字 if (reader["ResourceName"] != null && reader["ResourceName"].ToString() != "") { model.cName = reader["ResourceName"].ToString(); } //父节点id if (reader["ParentID"] != null && reader["ParentID"].ToString() != "") { model.cParentId = reader["ParentID"].ToString(); } //地址 if (reader["URL"] != null && reader["URL"].ToString() != "") { model.cUrl = reader["URL"].ToString(); } } return model; } private SqlDataReader ExecuteReader(string strSQL) { SqlConnection connection = new SqlConnection(connectionString); SqlCommand cmd = new SqlCommand(strSQL, connection); try { connection.Open(); SqlDataReader myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return myReader; } catch (System.Data.SqlClient.SqlException e) { throw e; } } } }
以上就是我的实现过程,刚开始研究这个树的时候绕的我跟着团团转,现在终于实现了,还是很高兴的,而且在这个小Demo中无意间还学会了在js方法中调用后台的方法,之前只有asp的控件方法会在后台写,js调用一般处理程序中的方法,呵呵,这么容易高兴呢!整个实现过程我已经上传到了,需要的话可以去下载,点击打开链接。
原文:http://blog.csdn.net/cjr15233661143/article/details/23366299