一个可以拖拽的异步按需加载树
2013-01-31 22:00 by tebato, 1287 阅读, 11 评论, 收藏, 编辑
最近完成了一个可以拖拽的异步按需加载树,顾名思义,这个树,至少支持以下三个功能。
1,节点可以拖拽(项目需要,已设置为只允许同级节点拖拽)。
2,异步加载(使用ajax加载数据,没啥好说的)。
3,按需要加载(点击展开按钮时,加载所需数据,不点击不加载,最小化的加载数据,最大化的支持大数据,哈哈)。
下面就这三个功能,分别贴出关键代码。
一,节点可以拖拽需要添加的代码。
1,先对树型控件的setting变量增加如下属性,并添加dropPrev,dropInner,dropNext方法,具体方法内容,请点击后面demo中网址右键。
edit: { enable: true, showRemoveBtn: false, showRenameBtn: false, drag: { autoExpandTrigger: true, prev: dropPrev, inner: dropInner, next: dropNext } }
2,在callback属性中加载如下代码,并分别新建两个方法beforeDrag和beforeDrop
callback: {
beforeDrag: beforeDrag,
beforeDrop: beforeDrop
}
至此拖拽功能基本实现,详细代码请自行扒下。
二:异步加载(使用ajax加载数据,没啥好说的),代码略。
三:按需要加载(点击展开按钮时,加载所需数据,不点击不加载)
1,在callback属性中加载如下代码,并新建方法beforeExpand,为什么是beforeExpand而不是onExpand呢,是因为在这个树中,预加载比加载完成后显示效果好。
callback: {
beforeExpand: beforeExpand
}
并且这里有个小技巧:若节点存在子节点,如何让其前面以文件夹图标显示,并且有展开符号“+”呢?我的作法时,在后台读取节点时,要遍历并判断是否有子节点,判断方法如下。
StringBuilder taskSb = new StringBuilder("["); var list = fileTypeRepository.GetFileTypeByParentId(new Guid(parentId)); foreach (var item in list) { taskSb.Append(string.Concat("{'id':'", item.ID,"'")); taskSb.Append(string.Concat(",'name':'", item.TypeName.Trim(),"'")); var childList = fileTypeRepository.GetFileTypeByParentId(item.ID); if (childList.Count > 0) { taskSb.Append(",children:[{'id':'"+Guid.NewGuid().ToString() +"','name':'wufei'}]"); } taskSb.Append("},"); }
这里如果有子节点,不管多少,虚加载一个名字为本人名字的节点,当然这个子节点在父节点展示时,自然会被干掉,同时真正的节点加载进来,并同时判断这一级节点是否有子节点,代码如下:
function beforeExpand(treeId, treeNode) { if (treeNode.children) { for (i = 0; i < treeNode.children.length; i++) { zTree.removeNode(treeNode.children[i]); } } if (treeNode.children) { for (i = 0; i < treeNode.children.length; i++) { zTree.removeNode(treeNode.children[i]); } } $.post("/Ashx/FileType.ashx?action=GetList", { parentId: treeNode.id }, function (txt) { var childNodes = eval(txt); for (i = 0; i < childNodes.length; i++) { var newNode = { id: childNodes[i].id, name: childNodes[i].name, children: childNodes[i].children, childOuter: false }; addTreeNode(treeNode, newNode); } }, "text"); return (treeNode.expand !== false); }
这里判断清除children用了两次,不得已,因为只清除一次,有子节点的节点不会被清除,所以需要清除两次,若是有人有更好的办法,一次就清除,不吝赐教。
至此,一个可以拖拽的异步按需加载树就基本完成,当然这个树,还不只这点功能,比如右键增加、删除节点,比如修改节点等等,都一一实现,更多效果,请查看demo网址:http://www.qicheba.net/FileManage/TypeManage
如果觉得有用,请猛击推荐,谢谢。
备注:这个Demo使用了一款功能强大的树型控件,名字叫:zTree,官网地址:http://www.ztree.me/v3/demo.php#_101
Suucha Expression 是一个表达式类,可适用于需要动态构造查询条件的前端(JavaScript)和后端(C#)的代码中。并且提供基于IQueryable的Where扩展。
获取源代码及安装
源代码:http://suuchaexp.codeplex.com
在Visual Studio中通过Nuget控制台安装:
Install-Package SuuchaExp //安装类库
Install-Package SuuchaExpJs //安装js
基本用法
//Javascript var searchParameter = new Suucha.SearchParameters(); searchParameter.Page = 1; searchParameter.PageSize = 20; searchParameter.Condition = Suucha.Expression.Equal('Name', 'name'); searchParameter.Condition = Suucha.Expression.And(searchParameter.Condition, Suucha.Expression.Equal('Code', '01')); //Json序列化后可以发送到服务端 var json = Ext.JSON.encode(searchParameter);
服务端可以直接使用SearchParameters的静态方法FromJson进行反序列化:
var search = SearchParameters.FromJson(json); var result = query.Where(search.Condition);
SuuchaExpression类及方法
suucha Expression提供三种类型的表达式:
- SuuchaMemberExpression,成员表达式
- SuuchaConstantExpression,常量表达式
- SuuchaBinaryExpression,二元表达式
他们都是继承自SuuchaExpression,SuuchaExpression还提供静态方法来创建这些表达式(Javascript中也有对应的方法)和构造简单的表达式树:
SuuchaMemberExpression Member(string name) | 根据成员名称创建一个成员表达式,name格式:"Code", "User.Name" |
SuuchaConstantExpression Constant(object value) | 创建一个常量表达式 |
SuuchaBinaryExpression Equal(string left, object right) | 创建一个等于的二元表达式,有多个重载 |
SuuchaBinaryExpression NotEqual(string left, object right) | 创建一个不等于的二元表达式,有多个重载 |
SuuchaBinaryExpression LessThan(string left, object right) | 创建一个小于的二元表达式,有多个重载 |
SuuchaBinaryExpression LessThanOrEqual(string left, object right) | 创建一个小于等于的二元表达式,有多个重载 |
SuuchaBinaryExpression GreaterThan(string left, object right) | 创建一个大于的二元表达式,有多个重载 |
SuuchaBinaryExpression GreaterThanOrEqual(string left, object right) | 创建一个大于等于的二元表达式,有多个重载 |
SuuchaBinaryExpression Like(string left, string right) | 创建一个Like操作的二元表达式,left是成员名称,right是要查找的字符串,可以使用通配符:% |
SuuchaBinaryExpression NotLike(string left, string right) | 创建一个NotLike操作的二元表达式 |
SuuchaBinaryExpression In(string left, string right) | 创建一个In操作的二元表达式,right必须是用逗号分隔的多个值 |
SuuchaBinaryExpression InLike(string left, string right) | 创建一个InLike操作的二元表达式,right必须是用逗号分隔的多个值 |
SuuchaBinaryExpression And(SuuchaBinaryExpression left, SuuchaBinaryExpression right) | 构造一个And操作的二元表达式 |
SuuchaBinaryExpression Or(SuuchaBinaryExpression left, SuuchaBinaryExpression right) | 构造一个Or操作的二元表达式 |
SuuchaExpression FromJson(string json) | 从Json字符串反序列化 |
基于IQueryable的扩展:
- IQueryable Where(this IQueryable source, SuuchaExpression expression)
- IQueryable<T> OrderBy<T>(this IQueryable<T> source, IEnumerable<SuuchaOrderBy> orderBy)
这里需要特别说明的是成员表达式中成员名称可以是Primitive属性(比如Code),也可以是关联属性的Primitive属性(比如User.Name),还支持集合关联属性,通过一个例子来说明下:
有一个角色类Role,一个用户类User,Role中有一个User的集合属性Users,现在需要查找角色的Users中User名称中包含"张"的角色,可以用如下的代码实现:
var condition = SuuchaExpression.Like("Users.Name","张"); var result = roles.Where(condition);
SuuchaExpression特别适合需要通过Javascript动态构建查询条件的场景,如果您感兴趣,可以下载源代码或通过nuget安装体验一下。