转载请注明作者及出处,谢谢
最近学习ASP.NET MVC 3,今天想试试jqGrid的TreeGrid模式,本以为跟着Demo一小会就能出效果,不料一直到晚上才搞定。于是把解决方案发出来以便刚接触jqGrid的兄弟参考。
需求:
显示树状结构的数据,如:部门列表。
@section head{ <script type="text/javascript"> $(function () { $('#treegrid').jqGrid({ treeGrid: true, treeGridModel: 'adjacency', ExpandColumn: 'DeptName', url: '/Department/Query/', datatype: 'json', mtype: 'GET', colNames: ['ID', '部门名称', 'ParentID', '主管', '主管职代', '说明', 'VisibilityValue'], colModel: [ { name: 'ID', index: 'ID', hidden: true, 1, key: true }, { name: 'DeptName', index: 'DeptName', 180 }, { name: 'ParentID', index: 'ParentID', hidden: true, 1 }, { name: 'Director', index: 'Director', 200, align: 'left' }, { name: 'DeputyID', index: 'DeputyID', 200 }, { name: 'Summary', index: 'Summary', 200 }, { name: 'VisibilityValue', index: 'VisibilityValue', hidden: true, 1 } ], pager: '#ptreegrid', height: 'auto' }); }) </script> }
小小的补充下,我使用Razor视图引擎,所以这一部分是视图里面定义javascript的Sectiion。个人感觉,除了不能“所见即所得”之外,这个引擎比传统的ASPX要好,但具体好在什么地方呢,也说不上来,感觉而已(不要敲我:))
今天有三分之一的时间花在一个小失误上,在上面的这段代码中,datatype被我写成了dataType,结果花了n小时,一个字一个字的找出来...
使用jqGrid TreeGrid,上面这些代码就足够了,设置还有多余的,比如pager不是必须的。
再小小的一段题外话,为什么网上的很多例子在使用jqGrid时使用的mtype为"POST"?,从RESTful的角度来说不应该是"GET"吗?莫非违背RESTful原则使用MVC比较有快感?
非常重要的工作是:必须把grid.treegrid.js引用进页面,我一直以为有那个jquery.jqGrid.min.js就够了,结果还是在加入了grid.treegrid.js后才能在点击一行后进入Controller。
剩下就是Controller里面的内容了。
public ActionResult Query(Guid? nodeid, int? n_level) { Guid? deptID = nodeid; int level = n_level != null ? (int)n_level + 1 : 0; JsonResult json = new JsonResult(); json.JsonRequestBehavior = JsonRequestBehavior.AllowGet; var deptMng = new DeptManager(); var depts = deptMng.GetChild(deptID, true); json.Data = new { page = 1, total = 1, records = depts.Count, rows = (from dept in depts select new { cell = new[] { dept.ID.ToString(), dept.DeptName, dept.ParentID != null ? dept.ParentID.ToString() : "", dept.DirectorID != null ? dept.DirectorID.ToString() : "", dept.Deputy != null ? dept.Deputy.ToString() : "", dept.Summary != null ? dept.Summary : "", dept.VisibilityValue.ToString(), level.ToString(), deptID != null ? deptID.ToString() : string.Empty, deptMng.GetChild(dept.ID,true).Count == 0 ? "true":"false", "false" } }) }; return json; }
说句实话,我灰常灰常喜欢”约定优于配置"这句话,很多时侯,背上的包袱总是自已加上去的,因此,为什么使用nodeid和n_level这两个参数名,我想还没有明白的就不用深究了,如果你想使用jqGrid的TreeGrid,那么你就使用这个参数列表吧。
当第一次加载视图时,nodeid和n_level均为空,因为你还没有点击树的任一节点,所以它哥俩默认为null。
当n_level为空时level为0,否则level = n_level + 1,为什么这样,后面提到。
deptMng.GetChild方法为获取指定部门ID的下一级子部门,不包括下二级。
ok,来到关键的地方了,json.Data里面放的匿名对象中,前三个成员比较简单,在能找到的所有的例子中,page和total都是1,所以我也就没有多想,名堂全在rows对象里面了:
先把你colNames和colModel里面需要的数据准备好,在本例中我使用了7个字段(真不明白,一个测试程序干嘛型那么多字段),从第八个开始有讲究:
level.ToString(),代表当前这行数据处于第level层,这也就是我为什么前面使用n_level+1的原因了,如果n_level为空的话,将要显示第0层,如果其不为空,说明当前level是n_level,将要显示的下一层level当然是n_level+1了。
第九个字段疑似存储父部门ID的,为什么是疑似呢,因为时间原因我还没有弄深入...(2011.9.11更新:可以肯定的是,这个字段就是存储父部门ID的,而且很重要的一点是,如果某节点的父ID为空的话,一定得使用null或是"null"来代替,而不能使用"",为啥呢?除非你不想使用排序(sorting)功能了)
第10个字段可以肯定的说,是存该部门是否包含子部门,记住:true代表没有子部门,false代表有子部门,似乎应该说成是否不存在子部门。
第11个字段,给个false就行了,原因不明...(2011.9.11更新: 这个字段的含义为:显示数据是否展开,true为展开,false为收起)
效果出来了。
刚开始使用jqGrid,很多东西还没有搞明白,只能依葫芦画瓢,见笑了:)
2011.9.11更新-----------------------
在这里有一个可以排序的例子,这里是关于排序问题的解决方案,这两个地址在说同一件事情。
这是有关TreeGrid的完整格式的样例:
{id: "1", name: "Cash", num: "100", debit: "400.00", credit: "250.00", balance: "150.00", enbl: "1", level: "0", parent: "null", isLeaf: false, expanded: false, loaded: true}
从level属性之前,是和业务有关的数据,之后,就是jqgrid的TreeGrid所需的数据了,基本上从属性名就可以看出作用。
一直在纳闷,官方文档到底在啥地方呢...
//2011.9.26应观众要求,做一个简单的示例吧