MVC+ZTree实现对树的CURD及拖拽操作
上一讲中,我们学习了如何使用zTree对一棵大树(大数据量的树型结构的数据表,呵呵,名称有点绕,但说的是事实)进行异步加载,今天这讲,我们来说说,如何去操作这棵大树,无非就是添加子节点,删除节点,编辑节点,节点之间的拖拽,节点位置的变化(排序)等等。
事实上,jquery.ZTree的demo已经把前台JS代码给的很清晰了,我们只要稍加修改,然后把后台CS代码写好就可以了,我将demo的前台代码做了简单的处理,减化了些代码,项目架构使用microsoft mvc 3.0
前台HTML代码如下:

- <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
- <script src="../../Scripts/JQuery-zTree/js/jquery-1.4.4.min.js"></script>
- <script src="../../Scripts/JQuery-zTree/js/jquery.ztree.all-3.5.min.js"></script>
- <style type="text/css">
- .ztree li span.button.add { margin-left: 2px; margin-right: -1px; background-position: -144px 0; vertical-align: top; *vertical-align: middle; }
- a { text-decoration: underline; }
- </style>
- <script type="text/javascript">
- /*
- 动态数据测试部分开始 */
- var log, className = "dark";
- var treeID = "treeDemo";
- var curDragNodes, autoExpandNode;
- var newCount = 1;
- //异步加载节点
- var setting4 = {
- data: {
- simpleData: {
- enable: true,
- idKey: "id",
- pIdKey: "pId",
- rootPId: null
- }
- },
- edit: {
- enable: true,
- editNameSelectAll: true,
- showRemoveBtn: showRemoveBtn,
- showRenameBtn: showRenameBtn,
- removeTitle: "删除",
- renameTitle: "编辑",
- drag: {
- autoExpandTrigger: true,
- prev: dropPrev,
- inner: dropInner,
- next: dropNext
- }
- },
- view: {
- addHoverDom: addHoverDom,
- removeHoverDom: removeHoverDom,
- selectedMulti: false
- },
- async: {
- //异步加载
- enable: true,
- url: "/ZTree/AsyncGetNodes",
- autoParam: ["id", "name", "pId"]
- },
- callback: {
- /*节点获取与展开回调*/
- beforeExpand: beforeExpand,
- onAsyncSuccess: onAsyncSuccess,
- onAsyncError: onAsyncError,
- /*编辑与删除回调*/
- beforeEditName: beforeEditName,
- beforeRemove: beforeRemove,
- beforeRename: beforeRename,
- onRemove: onRemove,
- onRename: onRename,
- /*拖动回调*/
- beforeDrag: beforeDrag,
- beforeDrop: beforeDrop,
- beforeDragOpen: beforeDragOpen,
- onDrag: onDrag,
- onDrop: onDrop,
- onExpand: onExpand
- }
- };
- function beforeEditName(treeId, treeNode) {
- className = (className === "dark" ? "" : "dark");
- var zTree = $.fn.zTree.getZTreeObj(treeID);
- zTree.selectNode(treeNode);
- return confirm("进入节点 -- " + treeNode.name + " 的编辑状态吗?");
- }
- function beforeRemove(treeId, treeNode) {
- className = (className === "dark" ? "" : "dark");
- var zTree = $.fn.zTree.getZTreeObj(treeID);
- zTree.selectNode(treeNode);
- return confirm("确认删除 节点 -- " + treeNode.name + " 吗?");
- }
- function beforeRename(treeId, treeNode, newName, isCancel) {
- className = (className === "dark" ? "" : "dark");
- if (newName.length == 0) {
- alert("节点名称不能为空.");
- var zTree = $.fn.zTree.getZTreeObj(treeID);
- setTimeout(function () { zTree.editName(treeNode) }, 10);
- return false;
- }
- return true;
- }
- function onRemove(e, treeId, treeNode) {
- $.ajax({
- url: '/ZTree/AsyncDelNodes', //url action是方法的名称
- data: { id: treeNode.id },
- type: 'POST',
- success: function (data) {
- alert(data);
- }
- });
- }
- function onRename(e, treeId, treeNode, isCancel) {
- alert("编辑了节点" + treeNode.id + " " + treeNode.name);
- $.ajax({
- url: '/ZTree/AsyncEditNodes', //url action是方法的名称
- data: { id: treeNode.id, name: treeNode.name },
- type: 'POST',
- success: function (data) {
- alert(data);
- }
- });
- }
- function showRemoveBtn(treeId, treeNode) {
- //return !treeNode.isFirstNode;
- return true;
- }
- function showRenameBtn(treeId, treeNode) {
- // return treeNode.isLastNode;
- return true;
- }
- function addHoverDom(treeId, treeNode) {
- var sObj = $("#" + treeNode.tId + "_span");
- if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0) return;
- var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
- + "' title='add node' onfocus='this.blur();'></span>";
- sObj.after(addStr);
- var btn = $("#addBtn_" + treeNode.tId);
- if (btn) btn.bind("click", function () {
- var zTree = $.fn.zTree.getZTreeObj(treeID);
- zTree.addNodes(treeNode, {
- id: (100 + newCount), pId: treeNode.id, name: "new node" + newCount
- });
- $.ajax({
- url: '/ZTree/AsyncAddNodes', //url action是方法的名称
- data: { id: (100 + newCount), pid: treeNode.id, name: "new node" + newCount },
- type: 'POST',
- success: function (data) {
- //异常完成后,刷新父节点及下面所有子节点
- zTree.reAsyncChildNodes(treeNode, "refresh");
- }
- });
- newCount++;
- return false;
- });
- };
- function removeHoverDom(treeId, treeNode) {
- $("#addBtn_" + treeNode.tId).unbind().remove();
- };
- function createTree() {
- $.ajax({
- url: '/ZTree/AsyncGetNodes', //url action是方法的名称
- data: { id: 0 },
- type: 'Get',
- dataType: "text", //可以是text,如果用text,返回的结果为字符串;如果需要json格式的,可是设置为json
- success: function (data) {
- $.fn.zTree.init($("#" + treeID), setting4, eval('(' + data + ')'));
- },
- error: function (msg) {
- alert(" 数据加载失败!" + msg);
- }
- });
- }
- function beforeExpand(treeId, treeNode) {
- if (!treeNode.isAjaxing) {
- return true;
- } else {
- alert("zTree 正在下载数据中,请稍后展开节点。。。");
- return false;
- }
- }
- function onAsyncSuccess(event, treeId, treeNode, msg) {
- }
- function onAsyncError() {
- alert(" 数据加载失败");
- }
- $(document).ready(function () {
- createTree();
- });
- function dropPrev(treeId, nodes, targetNode) {
- var pNode = targetNode.getParentNode();
- if (pNode && pNode.dropInner === false) {
- return false;
- } else {
- for (var i = 0, l = curDragNodes.length; i < l; i++) {
- var curPNode = curDragNodes[i].getParentNode();
- if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
- return false;
- }
- }
- }
- return true;
- }
- function dropInner(treeId, nodes, targetNode) {
- if (targetNode && targetNode.dropInner === false) {
- return false;
- } else {
- for (var i = 0, l = curDragNodes.length; i < l; i++) {
- if (!targetNode && curDragNodes[i].dropRoot === false) {
- return false;
- } else if (curDragNodes[i].parentTId && curDragNodes[i].getParentNode() !== targetNode && curDragNodes[i].getParentNode().childOuter === false) {
- return false;
- }
- }
- }
- return true;
- }
- function dropNext(treeId, nodes, targetNode) {
- var pNode = targetNode.getParentNode();
- if (pNode && pNode.dropInner === false) {
- return false;
- } else {
- for (var i = 0, l = curDragNodes.length; i < l; i++) {
- var curPNode = curDragNodes[i].getParentNode();
- if (curPNode && curPNode !== targetNode.getParentNode() && curPNode.childOuter === false) {
- return false;
- }
- }
- }
- return true;
- }
- function beforeDrag(treeId, treeNodes) {
- className = (className === "dark" ? "" : "dark");
- for (var i = 0, l = treeNodes.length; i < l; i++) {
- if (treeNodes[i].drag === false) {
- curDragNodes = null;
- return false;
- } else if (treeNodes[i].parentTId && treeNodes[i].getParentNode().childDrag === false) {
- curDragNodes = null;
- return false;
- }
- }
- curDragNodes = treeNodes;
- return true;
- }
- function beforeDragOpen(treeId, treeNode) {
- autoExpandNode = treeNode;
- return true;
- }
- function beforeDrop(treeId, treeNodes, targetNode, moveType, isCopy) {
- className = (className === "dark" ? "" : "dark");
- return true;
- }
- function onDrag(event, treeId, treeNodes) {
- className = (className === "dark" ? "" : "dark");
- }
- function onDrop(event, treeId, treeNodes, targetNode, moveType, isCopy) {
- className = (className === "dark" ? "" : "dark");
- $.ajax({
- url: '/ZTree/AsyncDragNodes', // url action是方法的名称
- data: { id: treeNodes[0].id, pid: targetNode.id, name: treeNodes[0].name, moveType: moveType, isCopy: isCopy },
- type: 'POST',
- success: function (data) {
- }
- });
- }
- function onExpand(event, treeId, treeNode) {
- if (treeNode === autoExpandNode) {
- className = (className === "dark" ? "" : "dark");
- }
- }
- </script>
- <div class="zTreeDemoBackground left">
- <ul id="treeDemo" class="ztree"></ul>
- </div>

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

- #region 对节点的操作
- /// <summary>
- /// 得到一级子节点
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public string AsyncGetNodes(int? id)
- {
- var model = irepository.GetEntities()
- .Where(i => i.ParentID == id).OrderBy(i => i.Sortable);
- return model.ToJson();
- }
- /// <summary>
- /// 添加节点
- /// </summary>
- /// <param name="id"></param>
- /// <param name="name"></param>
- /// <param name="pid"></param>
- /// <returns></returns>
- public string AsyncAddNodes(int id, string name, int pid)
- {
- try
- {
- //得到父对象,但设置它的isParent属性
- irepository.Modify(i => new Category
- {
- ID = pid,
- IsParent = true,
- });
- var entity = new Category
- {
- Name = name,
- ParentID = pid,
- CreateDate = DateTime.Now,
- Level = 1,
- IsParent = false,
- };
- irepository.Add(entity);
- return entity.ID.ToString();
- }
- catch (Exception ex)
- {
- return ex.Message;
- }
- }
- /// <summary>
- /// 编辑节点(重命名)
- /// </summary>
- /// <param name="id"></param>
- /// <param name="name"></param>
- /// <returns></returns>
- public string AsyncEditNodes(int id, string name)
- {
- try
- {
- irepository.Modify(i => new Category
- {
- ID = id,
- Name = name,
- });
- return "操作成功";
- }
- catch (Exception ex)
- {
- return ex.Message;
- }
- }
- /// <summary>
- /// 删除节点
- /// </summary>
- /// <param name="id"></param>
- /// <returns></returns>
- public string AsyncDelNodes(int id)
- {
- try
- {
- irepository.Remove(irepository.GetEntity(i => i.ID == id));
- return "操作成功";
- }
- catch (Exception ex)
- {
- return ex.Message;
- }
- }
- /// <summary>
- /// 拖拽节点
- /// </summary>
- /// <param name="id"></param>
- /// <param name="pid"></param>
- /// <param name="sortable"></param>
- /// <returns></returns>
- public string AsyncDragNodes(
- int id,
- int pid,
- string name,
- string moveType,
- bool isCopy)
- {
- try
- {
- var parent = irepository.GetEntity(i => i.ID == pid);
- var parentSons = irepository.GetEntities(i => i.ParentID == pid);
- var current = irepository.GetEntity(i => i.ID == id);
- if (moveType == "inner")
- parent.isParent = true;
- else if (parentSons == null || parentSons.Count() == 0)
- parent.isParent = false;
- if (isCopy)//复制,前台目前不能实现
- {
- irepository.Add(new Category
- {
- ParentID = pid,
- Name = name,
- CreateDate = DateTime.Now,
- });
- }
- else
- {
- if (moveType == "inner")
- {
- current.ParentID = pid;
- irepository.Modify(current);
- }
- else
- {
- current.ParentID = parent.ParentID;//同级移动时,与目标节点父ID相同
- current.Sortable = moveType == "next"
- ? parent.Sortable + 1
- : parent.Sortable - 1;
- irepository.Modify(current);
- }
- }
- irepository.Modify(parent);
- return "操作成功";
- }
- catch (Exception ex)
- {
- return ex.Message;
- }
- }
- #endregion

好了,上面的代码只是对树结果做的最基本的操作,其中拖拽时的复制操作(按着ctrl键,拖拽节点),后台没有进行实现。
MVC+ZTree实现对树的CURD及拖拽操作的更多相关文章
- 爱上MVC3~MVC+ZTree实现对树的CURD及拖拽操作
回到目录 上一讲中,我们学习了如何使用zTree对一棵大树(大数据量的树型结构的数据表,呵呵,名称有点绕,但说的是事实)进行异步加载,今天这讲,我们来说说,如何去操作这棵大树,无非就是添加子节点,删除 ...
- MVC小系列(十五)【MVC+ZTree实现对树的CURD及拖拽操作】
根据上一讲的可以加载一棵大树,这讲讲下如果操作这颗大树 <link href="../../Scripts/JQuery-zTree/css/zTreeStyle/zTreeStyle ...
- 【原创】MVC+ZTree实现权限树的功能
今天自己采用MVC+ZTree的技术实现权限树的功能,有需要的可以收藏一下. 1.需要引用的JS 文件 <link href="~/Content/ZTree/css/demo.css ...
- ztree插件的使用及列表项拖拽的实现(jQuery)+异步加载节点数据
为了实现如图所示的树状结构图,并使列表项可拖动到盒子里,研究了ztree这个插件的使用,并仔细研究了列表项的拖动事件.完成了预期需求,对jQuery的运用得到了提高.这个插件的功能非常强大,除了基本的 ...
- .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽
这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...
- 文件夹管理工具(MVC+zTree+layer)
文件夹管理工具(MVC+zTree+layer)(附源码) 写在前 之前写了一篇关于 文件夹与文件的操作的文章 操作文件方法简单总结(File,Directory,StreamReader,St ...
- 文件夹管理工具(MVC+zTree+layer)(附源码)
写在前 之前写了一篇关于 文件夹与文件的操作的文章 操作文件方法简单总结(File,Directory,StreamReader,StreamWrite ) 把常用的对于文件与文件夹的操作总结了一 ...
- 使用zTree插件实现可拖拽的树
在目前接触到的树插件中,我觉得zTree比较简单,也容易上手.有一次业务需求是将某对象分组树上的对象可以随意拖拽,相当于改变了对象的分组,因此我用到了zTree,对其进行了一些列学习. ...
- Jquery 可拖拽的Ztree
比较懒,就只贴关键代码吧,自己把有用的属性全部打印出来了,也加了不少注释. 保存后涉及到的排序问题,刷新问题还未考虑到,后面有的话再加. $.fn.zTree.init($("#ztree& ...
随机推荐
- linux shell 自动判断操作系统release 然后连接FTP yum源的脚本
如何搭建本地yum源见附录① 如何搭建FTP yum源见附录② 脚本正文: #!/bin/sh# CenterOS config yumOSV=`rpm -q --qf %{version} cent ...
- crontab 和 supervisor
crontab linux系统自带的工具,可以做定时任务,最小间隔是1分钟 配置crontab 命令 如果是以root用户编辑的,那么最后运行也是以root用户运行脚本文件 crontab -e 命令 ...
- (十八)python 3 回调函数
回调函数:把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的 ...
- 如何用scanf读入一个string
#include <stdio.h> #include <string> using namespace std; int main() { string a; a.resiz ...
- python--如何在线上环境优雅的修改配置文件?
1.如何在线上环境优雅的修改配置文件? 原配置文件 #原配置文件 global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 ...
- POJ-2773 Happy 2006,暴力2700ms+水过!
Happy 2006 这个题很可能会超时的,但我几乎暴力的方法2700ms+过了,可能是后台水 ...
- BZOJ 1303: [CQOI2009]中位数图 【水题】
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为1~n 的排列. Out ...
- ubuntu使用git时,终端不显示git分支。
1:问题描述: 在Windows环境下习惯使用git bash操作git分支,最近学习linux环境,发现linux环境终端不显示git分支,相关现象如下: 期望效果是: 我的linux环境 ...
- JAVA自定义监听器的示例代码
JAVA用户自定义事件监听完整例子 JAVA用户自定义事件监听完整例子- —sunfruit 很多介绍用户自定义事件都没有例子,或是例子不全,下面写了一个完整的例子,并写入了注释以便参考,完整 ...
- 权限对于目录和文件的具体含义 linux
权限对于具体文件的含义 文件上存储具体数据的地方,包括一般文件,数据库文件,二进制可执行文件等.因此权限对于文件的意义上这样都 r: 可读权限,表示可以读取该文件的内容 w:可写权限,表示可以编辑,新 ...