在做权限系统的时候,需要有一个树形的菜单。下图就是一个树形菜单的样式

但问题是,我们可以实现写死的树形菜单。什么是写死的?就是在前台代码中写好要加载的树形菜单是什么样子的。但是我们权限系统的要求是动态加载树形菜单,也就是根据数据库里面表的内容动态加载。

我首先要说的就是数据库设计,要想动态加载成树形菜单,数据库表中就一定要设置父节点ID和自身ID。通过父节点ID判断自身是属于哪一级菜单,而通过自身ID判断其对应的下一级菜单。这是数据库设计应该注意的地方,如果没有父节点和自身子节点,那么就没办法实现动态加载树形菜单。

动态加载树形菜单的实现利用的zTree。这里顺便提一下,zTree的网站做的真的很好,而且各种类型的zTree做的非常完美。我就是利用zTree来实现的,只不过与之不同的是zTree实现的树菜单也是在前台写好的,我们要做的就是将后台用数据库查询到的代码拼接成前台已经写好的代码格式。

这是前台写好的树菜单格式:

我们要做的就是将前台这种树形菜单格式在后台拼出来,而在树形菜单中显示的菜单名称是从数据库中查询出来的。最开始的时候尝试拼JSON串,但是事实证明,我失败了,拼出来的字符串运行的时候根本显示不出来

拼出的JSON串跟咱们要拼接的格式是不同的,JSON串拼接出来的格式适用于结构比较简单,这样利用循环可以将需要的字符串拼接出来。而我们需要的字符串是需要判断下一级是否有子节点的,这个利用JSON串我没有实现,只能实现一级菜单,而对应的实现三级菜单我没有拼出来。很遗憾,但是利用循环、遍历和DataTable的查询,最终实现了树形菜单字符串的拼接。下面是我实现的代码

这个对应的实现二级菜单的拼接

  1. public string getTree(string strTree)
  2. {
  3. string Chilstr = "";
  4. //获取DataTable
  5. zTreeBLL zTree = new zTreeBLL();
  6. DataTable dt = new DataTable();
  7. dt = zTree.QueryResource();
  8. //查询父节点有多少条不重复的数据
  9. zTreeBLL zTree1 = new zTreeBLL();
  10. DataTable dt1 = new DataTable();
  11. dt1 = zTree1.QueryParidNum();
  12. //父节点只能加到4
  13. //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++)   //Convert.ToInt32强制转换字符,把Object类型转换成int
  14. //{
  15. int parentId = 0;
  16. //查找第一个父节点有多少个,即初值为0的父节点
  17. DataRow[] rowsP = dt.Select("ParentID=" + parentId);
  18. //利用循环将父节点拼接起来
  19. for (int i = 0; i < rowsP.Length; i++)
  20. {
  21. //把rowsP里面的数值取出来
  22. foreach (DataRow drP in rowsP)
  23. {
  24. string parName = drP["ResourceName"].ToString();
  25. //strTree = "[{name:\""+ parName + "\"";
  26. strTree = "[{name:\"" + parName + "\"";
  27. DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1);
  28. if (rowsC.Length > 0)  //如果子节点不为0,则开始拼接子节点的字符串
  29. {
  30. //利用循环将父节点对应下的子节点串起来
  31. foreach (DataRow drC in rowsC)
  32. {
  33. string chilName = drC["ResourceName"].ToString();
  34. Chilstr = Chilstr + "{name:\"" + chilName + "\"}";
  35. Chilstr = Chilstr + ",";
  36. }
  37. Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1);
  38. strTree = strTree + ",children:[" + Chilstr + "]}];";
  39. }
  40. else
  41. {
  42. strTree = strTree + "\"}];";
  43. }
  44. }
  45. }
  46. //    parentId++;
  47. //}
  48. return strTree;
  49. }

这个对应的是多级菜单的拼接

  1. public string getTree(string strTree)
  2. {
  3. string Chilstr = "";
  4. //获取DataTable
  5. zTreeBLL zTree = new zTreeBLL();
  6. DataTable dt = new DataTable();
  7. dt = zTree.QueryResource();
  8. //查询父节点有多少条不重复的数据
  9. zTreeBLL zTree1 = new zTreeBLL();
  10. DataTable dt1 = new DataTable();
  11. dt1 = zTree1.QueryParidNum();
  12. //父节点只能加到4
  13. //for (int p = 0; p < Convert.ToInt32(dt1.Rows[0][0]); p++)   //Convert.ToInt32强制转换字符,把Object类型转换成int
  14. //{
  15. int parentId = 0;
  16. //查找第一个父节点有多少个,即初值为0的父节点
  17. DataRow[] rowsP = dt.Select("ParentID=" + parentId);
  18. //利用循环将父节点拼接起来
  19. for (int i = 0; i < rowsP.Length; i++)
  20. {
  21. //把rowsP里面的数值取出来
  22. foreach (DataRow drP in rowsP)
  23. {
  24. string parName = drP["ResourceName"].ToString();
  25. //strTree = "[{name:\""+ parName + "\"";
  26. strTree = "[{name:\"" + parName + "\"";
  27. DataRow[] rowsC = dt.Select("ParentID=" + parentId + 1);
  28. if (rowsC.Length > 0)  //如果子节点不为0,则开始拼接子节点的字符串
  29. {
  30. //利用循环将父节点对应下的子节点串起来
  31. foreach (DataRow drC in rowsC)
  32. {
  33. string Threestr = "";
  34. //判断二级菜单下对应的ID,也就是查找三级菜单的ParentID
  35. string chilFollow = drC["ID"].ToString();
  36. //查询三级菜单
  37. DataRow[] rowsThree = dt.Select("ParentID=" + chilFollow);
  38. //判断是否存在三级菜单
  39. if (rowsThree.Length > 0)
  40. {
  41. foreach (DataRow drThree in rowsThree)
  42. {
  43. string ThreeName = drThree["ResourceName"].ToString();
  44. Threestr = Threestr + "{name:\""+ThreeName+"\"}";
  45. Threestr = Threestr + ",";
  46. }
  47. Threestr = Threestr.Remove(Threestr.LastIndexOf(","), 1);
  48. string chilName = drC["ResourceName"].ToString();
  49. Chilstr = Chilstr + "{name:\"" + chilName + "\",children:["+Threestr+"]},";
  50. }
  51. //如果不存在三级菜单的话直接加载二级菜单
  52. else
  53. {
  54. string chilName = drC["ResourceName"].ToString();
  55. Chilstr = Chilstr + "{name:\"" + chilName + "\"}";
  56. Chilstr = Chilstr + ",";
  57. }
  58. }
  59. Chilstr = Chilstr.Remove(Chilstr.LastIndexOf(","), 1);
  60. strTree = strTree + ",children:[" + Chilstr + "]}];";
  61. }
  62. else
  63. {
  64. strTree = strTree + "\"}];";
  65. }
  66. }
  67. }
  68. return strTree;
  69. }

最终实现的效果

其实实现这个例子的方法还有很多种,比如说递归。虽然JSON串没有拼接成功,但是我觉得JSON串是可以实现的。只是鉴于个人能力的缘故最终没有拼接成功。动态加载树形菜单终于实现的,但是还有很多需要改进的地方,比如如何将这个方法封装起来,以至于可以无限的调用没有缺陷等,这是下一步值得继续探讨的问题。

C#动态加载树菜单的更多相关文章

  1. ExtJS 创建动态加载树

    Ext 中导航树的创建有两种方式:1.首先将所有的数据读出来,然后绑定到前台页面.2.每点击一个节点展开后加载子节点.在数据量比较小的时候使用第一种方式加载的会快一些,然而当数据量比较大的时候,我还是 ...

  2. easyui_tree 复选框 动态加载树

    controller动态获取单位用户树 #region 下拉树菜单 /// <summary> /// 获取工作人员树菜单 /// </summary> /// <par ...

  3. dtree实现动态加载树形菜单,动态插入树形菜单

    1.导入  dtree文件    dtree.css   img文件夹   dtree.js 2. 建立对应 的数据库      1      父ID     name    id 3    建立连接 ...

  4. EasyUI Jquery 动态加载树,点击节点加载

    <script type="text/javascript"> $(function() { $(document).ready(function() { $.post ...

  5. jQuery 动态加载树

    本案例中用到了jquery的 tree插件,在本文的附件中可以下载 jsp代码: <%@ page language="java" import="java.uti ...

  6. Vue + Element UI 实现权限管理系统 前端篇(十):动态加载菜单

    动态加载菜单 之前我们的导航树都是写死在页面里的,而实际应用中是需要从后台服务器获取菜单数据之后动态生成的. 我们在这里就用上一篇准备好的数据格式Mock出模拟数据,然后动态生成我们的导航菜单. 接口 ...

  7. Vue + Element UI 实现权限管理系统(动态加载菜单)

    动态加载菜单 之前我们的导航树都是写死在页面里的,而实际应用中是需要从后台服务器获取菜单数据之后动态生成的. 我们在这里就用上一篇准备好的数据格式Mock出模拟数据,然后动态生成我们的导航菜单. 接口 ...

  8. C#遍历XML文件动态加载菜单

    通过遍历XML文件动态加载菜单,顺便利用WebBrowser控件实现一个简单的桌面浏览器 效果如下: 代码如下: XMLFile1.xml <?xml version="1.0&quo ...

  9. C#自定义控件、用户控件、动态加载菜单按钮

    一.效果图,动态加载5个菜单按钮: 二.实现方法 1.创建用户控件 2.在用户控件拖入toolStrip 3.进入用户控件的Lood事件,这里自动添加5个选  ToolStripMenuItem,后期 ...

随机推荐

  1. 如何查看linux内核的版本号?

    zz:http://www.cnblogs.com/hnrainll/archive/2011/06/08/2074957.html 方法一: 命令: uname -a 作用: 查看系统内核版本号及系 ...

  2. HttpURLConnection 下载文件

    String fileUrl = request.getRequestURL().substring(0, request.getRequestURL().indexOf("/rest&qu ...

  3. wcf session开启

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] pu ...

  4. AsyncTask的缺陷以及解决方法

    1.AsyncTask常用于进行耗时操作,完成后更新主线程的UI. 2.缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程 ...

  5. NGUI Draw Calls优化(思路)

    用NGUI做界面的时候发现不注意GameObject(或者说Widget)的depth的话,单独运行界面时,Draw Calls挺高的: 网上搜了一下,大把的博客说的都是类似以下的原则: (PS:以下 ...

  6. 如何在asp.net中使用多线程及队列,异步处理一个耗时的任务(原创)

    最近想在使用.net 的队列处理一些耗时的工作.经过考虑,需要先设计一个类,类中包含一个静态的队列.主要是写队列和读取队列. public class PaperCalculator { // 用于存 ...

  7. 用PHP将Unicode 转化为UTF-8

    function unescape($str) { $str = rawurldecode($str); preg_match_all("/(?:%u.{4})|&#x.{4};|& ...

  8. NC WebService接口开发流程

    一.定义类: 接口类 包定义在public下,接口类名为I开头,Service结尾 实现类 包定义在private下,实现类名以ServiceImpl结尾 VO类 若有VO类,也放在public下 U ...

  9. AngularJs自定义指令详解(2) - template

    一些用于定义行为的指令,可能不需要使用template参数. 当指定template参数时,其值可以是一个字符串,表示一段HTML文本,也可以是一个函数,这函数接受两个参数:tElement和tAtt ...

  10. Android(Xamarin)之旅(三)

    前面两篇说到了Xamarin的安装和一些简单的控件,今天来说说一些对话框和提示信息,以及简单的布局元素. 一.对话框和提示信息 一.对话框 我们首先从简单的对话框开始. 1.普通对话框 在androi ...