使用Kendo Pager结合Kendo TreeList实现根节点分页的异常问题
Kendo TreeList根节点分页时页码传递异常问题
场景说明
尝试通过Kendo Pager结合Kendo TreeList实现树形结构的根节点分页,已启用远程数据绑定,子节点按需加载(展开行时加载),TreeList初始为折叠状态,服务器负责处理动态数据加载与分页逻辑。
示例树形层级:
- T1 = A -> B
- T2 = C -> D -> E
- T3 = X -> Y
设置页大小为2时,预期第1页显示T1、T2,第2页显示T3。但切换页码时,Pager传递给后端的页码不正确,比如点击第2页,后端收到的仍是第1页,Pager实际充当了TreeList的客户端分页器,未触发服务器端分页请求。
相关代码
TreeListView.cshtml
@(Html.Kendo().DataSource<TreeListViewModel>() .Name("TreeListDataSource") .TreeList(source => { source.Model(m => { m.Expanded(false); m.Id(f => f.ObjectID); m.ParentId(f => f.ParentID).Nullable(true); m.Field(f => f.Code); }); source.Read(read => read.Action("ReadTreeListdData", "TreeList").Data("BuildTreeListReadRequestData")).PageSize(2); }) ) @(Html.Kendo().TreeList<TreeListViewModel>() .Name("TreeList") .Columns(columns => { columns.Add().Field(f => f.Code); }) .DataSource("TreeListDataSource") ) @(Html.Kendo().Pager() .Name("TreeListPager") .DataSource("TreeListDataSource") )
TreeListController.cs
public JsonResult ReadTreeListData([DataSourceRequest] DataSourceRequest request, int? id) { int TotalTreeCount = 0; int pageSize = request.PageSize; int page = request.Page; var Result = GetTreeListDirectory(id, pageSize, page, out TotalTreeCount).ToTreeDataSourceResult(request, e => e.ObjectID, e => e.ParentID, e => id.HasValue ? e.ParentID == id : e.ParentID == null, e => e ); Result.Total = TotalTreeCount; //3 return Json(Result, JsonRequestBehavior.AllowGet); }
问题原因及解决办法
核心原因
Kendo TreeList的DataSource默认会在加载子节点时重置页码参数,且Pager与TreeList共享DataSource时,TreeList的远程加载逻辑会干扰Pager的页码传递。切换页码后,TreeList重新触发根节点读取时,DataSource的页码被内部逻辑覆盖,导致传递给后端的仍是初始页码。
解决步骤
分离分页与子节点加载逻辑
不要让TreeList的DataSource自动处理分页,改为手动维护分页参数,在读取根节点时传递Pager的页码和页大小。修改前端配置
- 移除DataSource上的
PageSize配置,在BuildTreeListReadRequestData函数中手动获取Pager参数:function BuildTreeListReadRequestData() { var pager = $("#TreeListPager").data("kendoPager"); return { page: pager.page(), pageSize: pager.pageSize(), id: null // 根节点加载时id为null,子节点加载时由TreeList自动传递 }; } - 禁用TreeList的自动服务器端分页,避免其干扰Pager逻辑:
@(Html.Kendo().TreeList<TreeListViewModel>() .Name("TreeList") .Columns(columns => { columns.Add().Field(f => f.Code); }) .DataSource(dataSource => dataSource .ServerOperation(false) // 禁用TreeList自动服务器分页 .Read(read => read.Action("ReadTreeListdData", "TreeList").Data("BuildTreeListReadRequestData")) // 其他Model配置... ) )
- 移除DataSource上的
调整后端处理逻辑
直接使用手动传递的分页参数,区分根节点分页与子节点加载场景:public JsonResult ReadTreeListData(int? id, int page, int pageSize) { int TotalTreeCount = 0; IEnumerable<TreeListViewModel> data; if (id.HasValue) { // 加载子节点,无需分页 data = GetTreeListDirectory(id, int.MaxValue, 1, out TotalTreeCount); } else { // 加载根节点,应用分页 data = GetTreeListDirectory(id, pageSize, page, out TotalTreeCount); } var result = data.ToTreeDataSourceResult( e => e.ObjectID, e => e.ParentID, e => id.HasValue ? e.ParentID == id : e.ParentID == null, e => e ); result.Total = TotalTreeCount; return Json(result, JsonRequestBehavior.AllowGet); }同步Pager总数据量
在根节点加载完成后,手动更新Pager的总数据条数:$("#TreeList").data("kendoTreeList").dataSource.bind("change", function(e) { var pager = $("#TreeListPager").data("kendoPager"); pager.total(this.total()); });
关键注意点
- TreeList原生不支持根节点分页,需通过手动控制参数实现。
- 子节点加载时跳过分页逻辑,仅根节点读取时应用分页。
- 避免Pager与TreeList的DataSource自动逻辑冲突,手动接管分页参数传递。
内容的提问来源于stack exchange,提问作者MKEF
相关产品推荐
相关产品推荐

