Kendo网格服务器端分组

时间:2014-05-14 08:55:59

标签: nhibernate kendo-grid grouping queryover

我正在使用Asp net 5,NHibernate 3.3和Kendo UI MVC包装器来生成网格以呈现客户订单表。数据库中已经有很多订单,数量也在不断增长。所以我决定使用服务器端分页来避免从数据库中获取所有订单。据我所知,你不能手动分页并委托过滤,排序和分组到ToDataSourceResult方法。无论是全有还是全无。因此,我试图实现所谓的'custom binding'。在我进行分组之前没问题。我需要先进行分组,然后在组内部进行排序,然后提取特定页面的数据以及所有这些数据而不将所有数据加载到内存中。我的代码是这样的(我把它全部放在一块以简化阅读):

var orderList = CurrentSession.QueryOver<Order>();

// Filtering. Filter is a search string obtained from DataSourceRequest
var disjunction = new Disjunction();
disjunction.Add(Restrictions.On<Order>(e => e.Number).IsLike("%" + filter + "%"));
disjunction.Add(Restrictions.On<Order>(e => e.Customer).IsLike("%" + filter + "%"));
orderList = orderList.Where(disjunction);

// Sorting. sortColumn is also from DataSourceRequest
switch (sortColumn)
{
        case "Number":
            orderList = orderList.OrderBy(x => x.Number).Desc;
            break;
        case "GeneralInfo.LastChangeDate":
            orderList = orderList.OrderBy(x => x.LastChangeDate).Desc;
            break;
        default:
            orderList = orderList.OrderBy(x => x.Number).Desc;
            break;
     }
}

// Total is required for kendo grid when you do paging manually
var total = orderList.RowCount();


var orders = orderList
    .Fetch(x => x.OrderGoods).Eager
    .Fetch(x => x.OrderComments).Eager
    .Fetch(x => x.Documents).Eager
    .Fetch(x => x.Partner).Eager
    .Skip((request.Page - 1)*request.PageSize).Take(request.PageSize).List();

我很乐意就如何在此处添加分组提出任何建议。

2 个答案:

答案 0 :(得分:12)

我几个月来一直在使用带有Kendo Grid的Kendo DataSource来计算服务器端分组。分页,排序和过滤相当容易。但无论出于何种原因,Telerik都没有为像分组这样的关键LOB流程提供足够的支持文档。我很高兴你发布了这个问题,所以我有机会分享我的代码。

解决方案

基本上,解决方案归结为了解两个关键部分,可以在以下示例项目中查看它们:https://www.dropbox.com/s/ygtk8rwl1hwjvth/KendoServerGrouping.zip?dl=0

您正在下载的Visual Studio(2012 | 2013)解决方案中有一个Web应用程序项目,其中包含对Kendo.Mvc库的引用。您可以从Telerik的控制面板安装程序下载最新的 UI for ASP.NET 二进制文件。安装后,二进制文件将位于以下Windows目录中: C:\ Program Files(x86)\ Telerik \ UI for ASP.NET MVC [Telerik发行版] \ wrappers \ aspnetmvc \ Binaries \ [您的MVC版本] \ Kendo.Mvc.dll

注意:我的解决方案使用Telerik的MVC传输机制,该机制提供完整的服务器端分页,过滤,排序,最值得注意的是分组。 但是,我使用纯JavaScript来配置Kendo DataSource而不是MVC包装器。不过,我最近在Telerik的文档中found a link显示了Razor / ASPX中的MVC包装器声明。

服务器魔术

基本上, magic 的第一部分是以下服务器端代码,位于 KendoServerGrouping.Web \ Controllers中的示例WebApi控制器中目录:

    [System.Web.Http.AcceptVerbs("GET", "ASPNETMVC-AJAX")]
    public Kendo.Mvc.UI.DataSourceResult GetAllAccounts([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))] Kendo.Mvc.UI.DataSourceRequest request)
    {
        var kendoRequest = new Kendo.Mvc.UI.DataSourceRequest
        {
            Page = request.Page,
            PageSize = request.PageSize,
            Filters = request.Filters,
            Sorts = request.Sorts,
            Groups = request.Groups,
            Aggregates = request.Aggregates
        };

        // Set this to your ORM or other data source
        IQueryable accounts = dbContext.Accounts;

        /*
           The data source can even be a MongoDB collection using the
           .AsQueryable() extension and the MongoDB C# driver

           var accounts = collection.FindAllAs<Account>().AsQueryable();
        */

        var data = accounts.ToDataSourceResult(kendoRequest);

        var result = new DataSourceResult()
        {
            AggregateResults = data.AggregateResults,
            Data = data.Data,
            Errors = data.Errors,
            Total = data.Total
        };

        return result;
    }

当用户与之交互时,网格将自动处理的四个服务器端操作中的任何一个都需要这些。特别注意方法上方的AcceptVerbs属性;它必须包含“ASPNETMVC-AJAX”属性才能使DataSourceRequest输入参数正常工作。 ToDataSourceResult()是最近版本的Kendo.Mvc.dll库提供的扩展,我在前面指出过。

上面的代码将(据我所知)与任何IQueryable数据源一起使用,例如来自ORM的数据源(我已经测试过实体框架和Telerik数据访问/开放访问)。我也能够使用MongoDB C#驱动程序对MongoDB集合进行分组。但是,这意味着概念验证,并且尚未经过性能测试

出于此示例的目的,WebAPI控制器中存在静态数据源以伪造IQueryable集合。当然,您可以在交换自己的数据源时从第45-57行删除静态数据

客户端魔术

Kendo DataSource自动从网格传入一个专门的DataSourceRequest对象,其中包含服务器端分页,过滤,排序和分组的所有参数, 提供 包装你的以下JavaScript中的DataSource模式:

schema: $.extend(true, {}, kendo.data.schemas["aspnetmvc-ajax"], {
});

这可能是我曾经追踪过的最难以捉摸的代码。几个月后,Telerik与Telerik进行了十几次交流,让他们咳嗽起来。即使在那时,它也是纯粹的偶然机会。为什么在他们的文档中缺少这样一个关键的细微差别超出了我的范围。

仔细检查每个Kendo DataSource配置设置到index.html文件的下半部分。最重要的是,要注意不存在的内容,例如batchmvcTransport选项。包括后一个选项会以某种方式否定上述“aspnetmvc-ajax”架构属性。

在DataSource的 parmaterMap 函数中,请注意当 - 并且仅当 - 执行读取操作时,必须存在以下行:

return mvcTransport.parameterMap(options, operation);

您还需要确保在DataSource执行之前将其包含在HTML中:

<script src="//cdn.kendostatic.com/[Version]/js/kendo.aspnetmvc.min.js"></script>

最终结果

运行 KendoServerGrouping.Web 项目( index.html ),如果一切顺利,网格将填充5条包含 AccountId的记录 AccountName AccountTypeCode CreatedOn 字段。如果您将可见网格行数设置为 2 并按 AccountTypeCode CreatedOn 分组,您将看到分组遍历分页,我认为这是你正在寻找的最终结果。

我希望示例项目有效并且非常适合您的情况。如果您有任何问题,请告诉我,我会尽力帮助您。

P.S。这是我给SO的第一篇文章,所以如果某些内容达不到SO标准,请放轻松。祝你好运!

答案 1 :(得分:0)

我想用this jewel I found on Telerik's forums添加@ aaron-jessen答案:

$("#grid").kendoGrid({
  dataSource: {
    type: "aspnetmvc-ajax",  // If missing may cause NULL values in ApiController
  }
})