上一讲中,我们学习了如何使用zTree对一棵大树(大数据量的树型结构的数据表,呵呵,名称有点绕,但说的是事实)进行异步加载,今天这讲,我们来说说,如何去操作这棵大树,无非就是添加子节点,删除节点,编辑节点,节点之间的拖拽,节点位置的变化(排序)等等。

事实上,jquery.ZTree的demo已经把前台JS代码给的很清晰了,我们只要稍加修改,然后把后台CS代码写好就可以了,我将demo的前台代码做了简单的处理,减化了些代码,项目架构使用microsoft mvc 3.0

前台HTML代码如下:

  1. <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
  2. <script src="../../Scripts/JQuery-zTree/js/jquery-1.4.4.min.js"></script>
  3. <script src="../../Scripts/JQuery-zTree/js/jquery.ztree.all-3.5.min.js"></script>
  4. <style type="text/css">
  5. .ztree li span.button.add { margin-left: 2px; margin-right: -1px; background-position: -144px 0; vertical-align: top; *vertical-align: middle; }
  6. a { text-decoration: underline; }
  7. </style>
  8. <script type="text/javascript">
  9. /*
  10. 动态数据测试部分开始 */
  11. var log, className = "dark";
  12. var treeID = "treeDemo";
  13. var curDragNodes, autoExpandNode;
  14. var newCount = 1;
  15.  
  16. //异步加载节点
  17. var setting4 = {
  18. data: {
  19. simpleData: {
  20. enable: true,
  21. idKey: "id",
  22. pIdKey: "pId",
  23. rootPId: null
  24. }
  25. },
  26. edit: {
  27. enable: true,
  28. editNameSelectAll: true,
  29. showRemoveBtn: showRemoveBtn,
  30. showRenameBtn: showRenameBtn,
  31. removeTitle: "删除",
  32. renameTitle: "编辑",
  33. drag: {
  34. autoExpandTrigger: true,
  35. prev: dropPrev,
  36. inner: dropInner,
  37. next: dropNext
  38. }
  39. },
  40. view: {
  41. addHoverDom: addHoverDom,
  42. removeHoverDom: removeHoverDom,
  43. selectedMulti: false
  44. },
  45. async: {
  46. //异步加载
  47. enable: true,
  48. url: "/ZTree/AsyncGetNodes",
  49. autoParam: ["id", "name", "pId"]
  50. },
  51. callback: {
  52. /*节点获取与展开回调*/
  53. beforeExpand: beforeExpand,
  54. onAsyncSuccess: onAsyncSuccess,
  55. onAsyncError: onAsyncError,
  56. /*编辑与删除回调*/
  57. beforeEditName: beforeEditName,
  58. beforeRemove: beforeRemove,
  59. beforeRename: beforeRename,
  60. onRemove: onRemove,
  61. onRename: onRename,
  62. /*拖动回调*/
  63. beforeDrag: beforeDrag,
  64. beforeDrop: beforeDrop,
  65. beforeDragOpen: beforeDragOpen,
  66. onDrag: onDrag,
  67. onDrop: onDrop,
  68. onExpand: onExpand
  69. }
  70. };
  71. function beforeEditName(treeId, treeNode) {
  72. className = (className === "dark" ? "" : "dark");
  73. var zTree = $.fn.zTree.getZTreeObj(treeID);
  74. zTree.selectNode(treeNode);
  75. return confirm("进入节点 -- " + treeNode.name + " 的编辑状态吗?");
  76. }
  77. function beforeRemove(treeId, treeNode) {
  78. className = (className === "dark" ? "" : "dark");
  79. var zTree = $.fn.zTree.getZTreeObj(treeID);
  80. zTree.selectNode(treeNode);
  81. return confirm("确认删除 节点 -- " + treeNode.name + " 吗?");
  82. }
  83. function beforeRename(treeId, treeNode, newName, isCancel) {
  84. className = (className === "dark" ? "" : "dark");
  85. if (newName.length == 0) {
  86. alert("节点名称不能为空.");
  87. var zTree = $.fn.zTree.getZTreeObj(treeID);
  88. setTimeout(function () { zTree.editName(treeNode) }, 10);
  89. return false;
  90. }
  91. return true;
  92. }
  93. function onRemove(e, treeId, treeNode) {
  94. $.ajax({
  95. url: '/ZTree/AsyncDelNodes', //url action是方法的名称
  96. data: { id: treeNode.id },
  97. type: 'POST',
  98. success: function (data) {
  99. alert(data);
  100. }
  101. });
  102.  
  103. }
  104. function onRename(e, treeId, treeNode, isCancel) {
  105. alert("编辑了节点" + treeNode.id + " " + treeNode.name);
  106. $.ajax({
  107. url: '/ZTree/AsyncEditNodes', //url action是方法的名称
  108. data: { id: treeNode.id, name: treeNode.name },
  109. type: 'POST',
  110. success: function (data) {
  111. alert(data);
  112. }
  113. });
  114.  
  115. }
  116. function showRemoveBtn(treeId, treeNode) {
  117. //return !treeNode.isFirstNode;
  118. return true;
  119. }
  120. function showRenameBtn(treeId, treeNode) {
  121. // return treeNode.isLastNode;
  122. return true;
  123. }
  124. function addHoverDom(treeId, treeNode) {
  125. var sObj = $("#" + treeNode.tId + "_span");
  126. if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return;
  127. var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
  128. + "' title='add node' onfocus='this.blur();'></span>";
  129. sObj.after(addStr);
  130. var btn = $("#addBtn_" + treeNode.tId);
  131. if (btn) btn.bind("click", function () {
  132. var zTree = $.fn.zTree.getZTreeObj(treeID);
  133. zTree.addNodes(treeNode, {
  134. id: (100 + newCount), pId: treeNode.id, name: "new node" + newCount
  135. });
  136. $.ajax({
  137. url: '/ZTree/AsyncAddNodes', //url action是方法的名称
  138. data: { id: (100 + newCount), pid: treeNode.id, name: "new node" + newCount },
  139. type: 'POST',
  140. success: function (data) {
  141. //异常完成后,刷新父节点及下面所有子节点
  142. zTree.reAsyncChildNodes(treeNode, "refresh");
  143. }
  144. });
  145. newCount++;
  146. return false;
  147. });
  148. };
  149. function removeHoverDom(treeId, treeNode) {
  150. $("#addBtn_" + treeNode.tId).unbind().remove();
  151. };
  152. function createTree() {
  153. $.ajax({
  154. url: '/ZTree/AsyncGetNodes', //url action是方法的名称
  155. data: { id: 0 },
  156. type: 'Get',
  157. dataType: "text", //可以是text,如果用text,返回的结果为字符串;如果需要json格式的,可是设置为json
  158. success: function (data) {
  159. $.fn.zTree.init($("#" + treeID), setting4, eval('(' + data + ')'));
  160. },
  161. error: function (msg) {
  162. alert(" 数据加载失败!" + msg);
  163. }
  164. });
  165. }
  166. function beforeExpand(treeId, treeNode) {
  167. if (!treeNode.isAjaxing) {
  168. return true;
  169. } else {
  170. alert("zTree 正在下载数据中,请稍后展开节点。。。");
  171. return false;
  172. }
  173. }
  174. function onAsyncSuccess(event, treeId, treeNode, msg) {
  175.  
  176. }
  177. function onAsyncError() {
  178. alert(" 数据加载失败");
  179. }
  180. $(document).ready(function () {
  181. createTree();
  182. });
  183.  
  184. function dropPrev(treeId, nodes, targetNode) {
  185.  
  186. var pNode = targetNode.getParentNode();
  187. if (pNode && pNode.dropInner === false) {
  188. return false;
  189. } else {
  190. for (var i = 0, l = curDragNodes.length; i < l; i++) {
  191. var curPNode = curDragNodes[i].getParentNode();
  192. if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
  193. return false;
  194. }
  195. }
  196. }
  197. return true;
  198. }
  199. function dropInner(treeId, nodes, targetNode) {
  200.  
  201. if (targetNode && targetNode.dropInner === false) {
  202. return false;
  203. } else {
  204. for (var i = 0, l = curDragNodes.length; i < l; i++) {
  205. if (!targetNode && curDragNodes[i].dropRoot === false) {
  206. return false;
  207. } else if (curDragNodes[i].parentTId && curDragNodes[i].getParentNode() !== targetNode && curDragNodes[i].getParentNode().childOuter === false) {
  208. return false;
  209. }
  210. }
  211. }
  212. return true;
  213. }
  214. function dropNext(treeId, nodes, targetNode) {
  215.  
  216. var pNode = targetNode.getParentNode();
  217. if (pNode && pNode.dropInner === false) {
  218. return false;
  219. } else {
  220. for (var i = 0, l = curDragNodes.length; i < l; i++) {
  221. var curPNode = curDragNodes[i].getParentNode();
  222. if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
  223. return false;
  224. }
  225. }
  226. }
  227. return true;
  228. }
  229. function beforeDrag(treeId, treeNodes) {
  230. className = (className === "dark" ? "" : "dark");
  231. for (var i = 0, l = treeNodes.length; i < l; i++) {
  232. if (treeNodes[i].drag === false) {
  233. curDragNodes = null;
  234. return false;
  235. } else if (treeNodes[i].parentTId && treeNodes[i].getParentNode().childDrag === false) {
  236. curDragNodes = null;
  237. return false;
  238. }
  239. }
  240. curDragNodes = treeNodes;
  241. return true;
  242. }
  243. function beforeDragOpen(treeId, treeNode) {
  244. autoExpandNode = treeNode;
  245. return true;
  246. }
  247. function beforeDrop(treeId, treeNodes, targetNode, moveType, isCopy) {
  248. className = (className === "dark" ? "" : "dark");
  249. return true;
  250. }
  251. function onDrag(event, treeId, treeNodes) {
  252. className = (className === "dark" ? "" : "dark");
  253. }
  254. function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) {
  255. className = (className === "dark" ? "" : "dark");
  256. $.ajax({
  257. url: '/ZTree/AsyncDragNodes', // url action是方法的名称
  258. data: { id: treeNodes[0].id, pid: targetNode.id, name: treeNodes[0].name, moveType: moveType, isCopy: isCopy },
  259. type: 'POST',
  260. success: function (data) {
  261. }
  262. });
  263.  
  264. }
  265. function onExpand(event, treeId, treeNode) {
  266. if (treeNode === autoExpandNode) {
  267. className = (className === "dark" ? "" : "dark");
  268. }
  269. }
  270. </script>
  271.  
  272. <div class="zTreeDemoBackground left">
  273. <ul id="treeDemo" class="ztree"></ul>
  274. </div>

面各种JS事件,所对应的MVC代码如下:

  1. #region 对节点的操作
  2. /// <summary>
  3. /// 得到一级子节点
  4. /// </summary>
  5. /// <param name="id"></param>
  6. /// <returns></returns>
  7. public string AsyncGetNodes(int? id)
  8. {
  9. var model = irepository.GetEntities()
  10. .Where(i => i.ParentID == id).OrderBy(i => i.Sortable);
  11.  
  12. return model.ToJson();
  13. }
  14. /// <summary>
  15. /// 添加节点
  16. /// </summary>
  17. /// <param name="id"></param>
  18. /// <param name="name"></param>
  19. /// <param name="pid"></param>
  20. /// <returns></returns>
  21. public string AsyncAddNodes(int id, string name, int pid)
  22. {
  23. try
  24. {
  25. //得到父对象,但设置它的isParent属性
  26. irepository.Modify(i => new Category
  27. {
  28. ID = pid,
  29. IsParent = true,
  30. });
  31.  
  32. var entity = new Category
  33. {
  34. Name = name,
  35. ParentID = pid,
  36. CreateDate = DateTime.Now,
  37. Level = 1,
  38. IsParent = false,
  39. };
  40. irepository.Add(entity);
  41.  
  42. return entity.ID.ToString();
  43. }
  44. catch (Exception ex)
  45. {
  46.  
  47. return ex.Message;
  48. }
  49.  
  50. }
  51. /// <summary>
  52. /// 编辑节点(重命名)
  53. /// </summary>
  54. /// <param name="id"></param>
  55. /// <param name="name"></param>
  56. /// <returns></returns>
  57. public string AsyncEditNodes(int id, string name)
  58. {
  59. try
  60. {
  61. irepository.Modify(i => new Category
  62. {
  63. ID = id,
  64. Name = name,
  65. });
  66. return "操作成功";
  67. }
  68. catch (Exception ex)
  69. {
  70.  
  71. return ex.Message;
  72. }
  73. }
  74. /// <summary>
  75. /// 删除节点
  76. /// </summary>
  77. /// <param name="id"></param>
  78. /// <returns></returns>
  79. public string AsyncDelNodes(int id)
  80. {
  81. try
  82. {
  83. irepository.Remove(irepository.GetEntity(i => i.ID == id));
  84. return "操作成功";
  85. }
  86. catch (Exception ex)
  87. {
  88. return ex.Message;
  89. }
  90. }
  91. /// <summary>
  92. /// 拖拽节点
  93. /// </summary>
  94. /// <param name="id"></param>
  95. /// <param name="pid"></param>
  96. /// <param name="sortable"></param>
  97. /// <returns></returns>
  98. public string AsyncDragNodes(
  99. int id,
  100. int pid,
  101. string name,
  102. string moveType,
  103. bool isCopy)
  104. {
  105. try
  106. {
  107. var parent = irepository.GetEntity(i => i.ID == pid);
  108. var parentSons = irepository.GetEntities(i => i.ParentID == pid);
  109. var current = irepository.GetEntity(i => i.ID == id);
  110. if (moveType == "inner")
  111. parent.isParent = true;
  112. else if (parentSons == null || parentSons.Count() == 0)
  113. parent.isParent = false;
  114. if (isCopy)//复制,前台目前不能实现
  115. {
  116. irepository.Add(new Category
  117. {
  118. ParentID = pid,
  119. Name = name,
  120. CreateDate = DateTime.Now,
  121. });
  122. }
  123. else
  124. {
  125. if (moveType == "inner")
  126. {
  127. current.ParentID = pid;
  128. irepository.Modify(current);
  129. }
  130. else
  131. {
  132. current.ParentID = parent.ParentID;//同级移动时,与目标节点父ID相同
  133. current.Sortable = moveType == "next"
  134. ? parent.Sortable + 1
  135. : parent.Sortable - 1;
  136. irepository.Modify(current);
  137. }
  138. }
  139. irepository.Modify(parent);
  140. return "操作成功";
  141. }
  142. catch (Exception ex)
  143. {
  144.  
  145. return ex.Message;
  146. }
  147. }
  148. #endregion

好了,上面的代码只是对树结果做的最基本的操作,其中拖拽时的复制操作(按着ctrl键,拖拽节点),后台没有进行实现。

MVC+ZTree实现对树的CURD及拖拽操作的更多相关文章

  1. 爱上MVC3~MVC+ZTree实现对树的CURD及拖拽操作

    回到目录 上一讲中,我们学习了如何使用zTree对一棵大树(大数据量的树型结构的数据表,呵呵,名称有点绕,但说的是事实)进行异步加载,今天这讲,我们来说说,如何去操作这棵大树,无非就是添加子节点,删除 ...

  2. MVC小系列(十五)【MVC+ZTree实现对树的CURD及拖拽操作】

    根据上一讲的可以加载一棵大树,这讲讲下如果操作这颗大树 <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle ...

  3. 【原创】MVC+ZTree实现权限树的功能

    今天自己采用MVC+ZTree的技术实现权限树的功能,有需要的可以收藏一下. 1.需要引用的JS 文件 <link href="~/Content/ZTree/css/demo.css ...

  4. ztree插件的使用及列表项拖拽的实现(jQuery)+异步加载节点数据

    为了实现如图所示的树状结构图,并使列表项可拖动到盒子里,研究了ztree这个插件的使用,并仔细研究了列表项的拖动事件.完成了预期需求,对jQuery的运用得到了提高.这个插件的功能非常强大,除了基本的 ...

  5. .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽

    这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...

  6. 文件夹管理工具(MVC+zTree+layer)

    文件夹管理工具(MVC+zTree+layer)(附源码)   写在前 之前写了一篇关于 文件夹与文件的操作的文章  操作文件方法简单总结(File,Directory,StreamReader,St ...

  7. 文件夹管理工具(MVC+zTree+layer)(附源码)

    写在前 之前写了一篇关于 文件夹与文件的操作的文章  操作文件方法简单总结(File,Directory,StreamReader,StreamWrite )  把常用的对于文件与文件夹的操作总结了一 ...

  8. 使用zTree插件实现可拖拽的树

    在目前接触到的树插件中,我觉得zTree比较简单,也容易上手.有一次业务需求是将某对象分组树上的对象可以随意拖拽,相当于改变了对象的分组,因此我用到了zTree,对其进行了一些列学习.         ...

  9. Jquery 可拖拽的Ztree

    比较懒,就只贴关键代码吧,自己把有用的属性全部打印出来了,也加了不少注释. 保存后涉及到的排序问题,刷新问题还未考虑到,后面有的话再加. $.fn.zTree.init($("#ztree& ...

随机推荐

  1. linux shell 自动判断操作系统release 然后连接FTP yum源的脚本

    如何搭建本地yum源见附录① 如何搭建FTP yum源见附录② 脚本正文: #!/bin/sh# CenterOS config yumOSV=`rpm -q --qf %{version} cent ...

  2. crontab 和 supervisor

    crontab linux系统自带的工具,可以做定时任务,最小间隔是1分钟 配置crontab 命令 如果是以root用户编辑的,那么最后运行也是以root用户运行脚本文件 crontab -e 命令 ...

  3. (十八)python 3 回调函数

    回调函数:把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的 ...

  4. 如何用scanf读入一个string

    #include <stdio.h> #include <string> using namespace std; int main() { string a; a.resiz ...

  5. python--如何在线上环境优雅的修改配置文件?

    1.如何在线上环境优雅的修改配置文件? 原配置文件 #原配置文件 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 ...

  6. POJ-2773 Happy 2006,暴力2700ms+水过!

                                                         Happy 2006 这个题很可能会超时的,但我几乎暴力的方法2700ms+过了,可能是后台水 ...

  7. BZOJ 1303: [CQOI2009]中位数图 【水题】

    给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Out ...

  8. ubuntu使用git时,终端不显示git分支。

    1:问题描述: 在Windows环境下习惯使用git bash操作git分支,最近学习linux环境,发现linux环境终端不显示git分支,相关现象如下:      期望效果是: 我的linux环境 ...

  9. JAVA自定义监听器的示例代码

    JAVA用户自定义事件监听完整例子 JAVA用户自定义事件监听完整例子- —sunfruit     很多介绍用户自定义事件都没有例子,或是例子不全,下面写了一个完整的例子,并写入了注释以便参考,完整 ...

  10. 权限对于目录和文件的具体含义 linux

    权限对于具体文件的含义 文件上存储具体数据的地方,包括一般文件,数据库文件,二进制可执行文件等.因此权限对于文件的意义上这样都 r: 可读权限,表示可以读取该文件的内容 w:可写权限,表示可以编辑,新 ...