Fork me on GitHub
一个可以拖拽的异步按需加载树

一个可以拖拽的异步按需加载树

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安装体验一下。

posted on 2013-02-01 18:21  HackerVirus  阅读(158)  评论(0编辑  收藏  举报