2014-05-14 71 views
2

我正在使用Asp网络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(); 

我会很高兴对如何添加分组这里的任何建议。

回答

10

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

基本上,溶液归结为知道2层键的部分,并且它们可以在下面的示例项目被看作:https://www.dropbox.com/s/ygtk8rwl1hwjvth/KendoServerGrouping.zip?dl=0

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

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

服务器魔术

基本上的第一部分是以下服务器端代码,驻留在KendoServerGrouping.Web \控制器目录中的样本的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; 
    } 

这就是所有你需要的四个服务器端操作中的任何一个,当网格将自动神奇地处理ser与它进行交互。要特别注意方法上方的AcceptVerbs属性;它必须包含“ASPNETMVC-AJAX”属性,以使DataSourceRequest输入参数正常工作。 ToDataSourceResult()是由我刚才指出的Kendo.Mvc.dll库的最新版本提供的扩展。

上面的代码(据我所知)可以与任何IQueryable数据源一起使用,比如来自ORM的数据源(我已经测试过Entity Framework和Telerik Data Access/Open Access)。我也可以使用MongoDB C#驱动程序对MongoDB集合进行分组。然而,这是一个概念验证,它没有经过性能测试

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

客户魔术

剑道数据源在专门DataSourceRequest对象自动传递从含为服务器端的寻呼,过滤,排序和分组的所有参数的网格,提供你包住下面的JavaScript内部数据源模式:

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

这也许是我的代码的最难以捉摸线已经过追查。几个月后,Telerik花了十几笔交易让他们咳嗽起来。即使如此,它被揭露出来也是纯粹的机会。为什么在他们的文档中缺乏这样一个重要的细微差别超出了我的想象。

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

在数据源的parmaterMap功能,记时 - 只有当 - 执行读操作,以下行必须存在:

return mvcTransport.parameterMap(options, operation); 

你也想一定要包括这在你的HTML,之前的数据源,执行:

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

最终结果

运行KendoServerGrouping.Web项目(的index.html),如果一切顺利的话,网格将与5条记录包含填充ACCOUNTID帐户名AccountTypeCodeCreatedOn领域。如果将可见网格行的数量设置为和组AccountTypeCodeCreatedOn,您将看到分组遍历分页,我相信这是您正在查找的最终结果。

我希望示例项目能够正常工作,非常适合您的情况。如果您有任何问题,请告诉我,我会尽我所能提供帮助。

P.S.这是我的第一篇文章,所以如果某些东西不符合SO标准,请对我轻松点。祝你好运!

+0

非常感谢你这样详细的解答!你提供的示例项目工作得很好,它演示了我需要的行为。这将是一个很好的起点。顺便说一下,我很惊讶地看到解决方案非常棘手。 Telerik在这里肯定有一些改进空间。 – vsevolod

+0

我很高兴它解决了!我完全同意解决方案很棘手;它不应该很难执行服务器端分组。祝你好运! –

+0

而不是使用Telerik的DataSourceRequest,你也可以尝试使用[KendoGridBinderEx](https://github.com/StefH/KendoGridBinderEx) –

0

我想补充到@亚伦 - 杰森的回答与this jewel I found on Telerik's forums

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

使用这个'type:“aspnetmvc-ajax”'意味着Kendo UI Grid会忽略'parameterMap:function(){...}'。请使用'dataSource.transport.read.data:function(e){...}' –