2014-05-14 126 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){...}' –