@code Dim grid As Kendo.Mvc.UI.Grid(Of BO.Models.Location) = Html.Kendo.Grid(Of BO.Models.Location)(Model.Locations) _ .Name("LocationGrid") _ .EnableCustomBinding(True) _ .Columns(Sub(c) c.Bound(Function(b) b.ZipCode) c.ForeignKey(Function(f) f.StateId, Model.States.AsEnumerable, "Id", "Name") c.Bound(Function(b) b.City) c.Bound(Function(b) b.Longitude) c.Bound(Function(b) b.Latitude) 'c.Command(Sub(m) ' m.Edit() ' 'm.Custom("Details").Text("Details").Action("details", "location", New With {.area = "admin"}) ' End Sub).Width(210) End Sub) _ .DataSource(Function(d) _ d.Ajax.Read("GetLocations", "Location", New With {.area = "admin"}).Update("UpdateLocation", "Location", New With {.area = "admin"}) _ .ServerOperation(True).Model(Sub(model) model.Id(Function(p) p.LocationId)).Total(Model.RecordCount)).Sortable().Filterable().Pageable() grid.Render()End CodeFunction Index() As ActionResult Return View(New BO.Models.LocationGridModel)End FunctionFunction GetLocations(<Kendo.Mvc.UI.DataSourceRequestAttribute(Prefix:="Grid")> request As Kendo.Mvc.UI.DataSourceRequest) As JsonResult If request.PageSize.Equals(0) Then request.PageSize = 10 End If Dim LocationGridModel As BO.Models.LocationGridModel = New BO.Models.LocationGridModel(request) Return Json(LocationGridModel.Locations.ToList)End Function<HttpPost>Function UpdateLocation(id As Integer, collection As FormCollection, <Kendo.Mvc.UI.DataSourceRequestAttribute(Prefix:="Grid")> request As Kendo.Mvc.UI.DataSourceRequest) As JsonResult Dim Location As EF.Location = db.Locations.Find(id) Try UpdateModel(Location) db.SaveChanges() Catch ex As Exception Throw End Try Dim LocationGridModel As BO.Models.LocationGridModel = New BO.Models.LocationGridModel(request) Return Json(LocationGridModel.Locations.ToList)End FunctionImports System.Collections.ObjectModelImports System.ComponentModelImports Kendo.MvcNamespace Models Public Class LocationGridModel Public Property PageSize As Integer = 15 Private _Locations As ReadOnlyCollection(Of BO.Models.Location) Public ReadOnly Property Locations As ReadOnlyCollection(Of BO.Models.Location) Get Return _Locations End Get End Property Public Property States As ReadOnlyCollection(Of BO.Models.StateDropDown) Public Property RecordCount As Integer Sub New() Using db As EF.HomelyEntities = New EF.HomelyEntities Me._Locations = ConvertToDbMoldelsLocation(db.Locations.OrderBy(Function(o) o.LocationId).Take(Me.PageSize)) Me.RecordCount = db.Locations.Count Me.States = New ReadOnlyCollection(Of BO.Models.StateDropDown)(db.States.Where(Function(w) w.CountryId.Equals(2)).OrderBy(Function(o) o.Name).Select(Function(s) New BO.Models.StateDropDown With {.Id = s.StateId, .Name = s.Name}).ToList) End Using End Sub Sub New(request As UI.DataSourceRequest) Using db As EF.HomelyEntities = New EF.HomelyEntities Me._Locations = GetData(request, Me.RecordCount) Me.States = New ReadOnlyCollection(Of BO.Models.StateDropDown)(db.States.Where(Function(w) w.CountryId.Equals(2)).OrderBy(Function(o) o.Name).Select(Function(s) New BO.Models.StateDropDown With {.Id = s.StateId, .Name = s.Name}).ToList) End Using End Sub ''' <summary> ''' Reterns location data for kendo grid ''' </summary> ''' <param name="request">Kendo.Mvc.UI.DataSourceRequest</param> ''' <param name="recordCount">Integer</param> ''' <returns>ReadOnlyCollection(Of BO.Models.Location)</returns> ''' <remarks></remarks> Private Function GetData(ByVal request As Kendo.Mvc.UI.DataSourceRequest, ByRef recordCount As Integer) As ReadOnlyCollection(Of BO.Models.Location) Using db As EF.HomelyEntities = New EF.HomelyEntities 'todo remove recordcount Dim data As IQueryable(Of EF.Location) = db.Locations If request.Sorts.Any Then For Each sortDescriptor As SortDescriptor In request.Sorts data = SortLocation(sortDescriptor, data) Next Else data = data.OrderBy(Function(o) o.LocationId) End If If request.Filters.Any() Then data = data.Where(ExpressionBuilder.Expression(Of EF.Location)(request.Filters)) End If recordCount = data.Count If request.PageSize > 0 Then data = data.Skip((request.Page - 1) * request.PageSize) data = data.Take(request.PageSize) End If Return ConvertToDbMoldelsLocation(data) End Using End Function Private Function SortLocation(sortDescriptor As SortDescriptor, data As IQueryable(Of EF.Location)) As IQueryable(Of EF.Location) If sortDescriptor.SortDirection.Equals(ListSortDirection.Ascending) Then Select Case sortDescriptor.Member Case "LocationId" data = data.OrderBy(Function(o) o.LocationId) Case "ZipCode" data = data.OrderBy(Function(o) o.ZipCode) Case "StateId" data = data.OrderBy(Function(o) o.StateId) Case "Latitude" data = data.OrderBy(Function(o) o.Latitude) Case "Longitude" data = data.OrderBy(Function(o) o.Longitude) Case "City" data = data.OrderBy(Function(o) o.City) End Select Else Select Case sortDescriptor.Member Case "LocationId" data = data.OrderByDescending(Function(o) o.LocationId) Case "ZipCode" data = data.OrderByDescending(Function(o) o.ZipCode) Case "StateId" data = data.OrderByDescending(Function(o) o.StateId) Case "Latitude" data = data.OrderByDescending(Function(o) o.Latitude) Case "Longitude" data = data.OrderByDescending(Function(o) o.Longitude) Case "City" data = data.OrderByDescending(Function(o) o.City) End Select End If Return data End Function ''' <summary> ''' Converts to poco model to use in grid ''' </summary> ''' <param name="data">IQueryable(Of EF.Location)</param> ''' <returns>ReadOnlyCollection(Of BO.Models.Location)</returns> ''' <remarks></remarks> Private Shared Function ConvertToDbMoldelsLocation(data As IQueryable(Of EF.Location)) As ReadOnlyCollection(Of BO.Models.Location) Return New ReadOnlyCollection(Of BO.Models.Location)(data.Select(Function(s) New BO.Models.Location With { .ZipCode = s.ZipCode, .StateId = s.StateId, .City = s.City, .Longitude = s.Longitude, .Latitude = s.Latitude, .LocationId = s.LocationId }).ToList) End Function End ClassEnd Namespace@(Html.Kendo().Grid<NatureOfStudyViewModel>() .Name("NatureOfStudyGrid") .Columns(columns => { columns.Bound(item => item.NatureOfStudy); }) .DataSource(ds => ds .Ajax() .Model(model => { model.Id(m => m.NatureOfStudy); }) .Read(read => read.Action("NatureOfStudyDataSource", "Lists")) .Create(create => create.Action("NatureOfStudyCreate","Lists")) .Destroy(destroy => destroy.Action("NatureOfStudyDelete","Lists")) .Events(events => events.Error("listValueDataSource_error")) ) .Pageable() .ToolBar(commands => commands.Create()) .Editable(edit => edit.Mode(GridEditMode.PopUp)) )
Specs
Kendo: 2012.3.1114
Net: 4.5
MVC: 4.0
Problem
I am binding my grid using a DataTable as the Model and need to have aggregate values. I have to use the datatable as I have a lot of data that is being sent over from the web service. If wrapped as XML it was over 55 MB for 21 columns and 14,400 rows so we converted the SQL DataTable to CSV and then sent the string over. That resulted in a file around 5MB.
The data that I a getting has no model as there can easily be 200+ columns depending on the query so making a data model is sadly out of the question.
If I use the snippet below as my base (taken from the Kendo UI Code Library) there seems to be no way to set up the aggregate functions
@(Html.Kendo().Grid(Model) .Name("Grid") .Columns(columns => { foreach (System.Data.DataColumn column in Model.Columns) { columns.Bound(column.DataType, column.ColumnName); } }) .Pageable() .Sortable() .Scrollable() .Filterable() .Groupable() .DataSource(dataSource => dataSource .Ajax() .Read(read => read.Action("Read", "Home")) ) )Back in the days of the Telerik MVC controls I could set up the aggregate function you could setup the aggregate while adding the bound column but in the Kendo UI wrapper that has been moved down to be inside of the DataSource.
Telerik Grid:
columns.Bound("ColumnName").Aggregate(aggregates => aggregates.Count().Min().Max())If I try and set up the agregate down in the DataSource I get a lovely exception "'count' is undefined" which is a bit vague.
if (column.ColumnName == "ProductID") { columns .Bound(column.DataType, column.ColumnName) .ClientFooterTemplate("Count: #=count#"); } ... .Aggregates(aggregates => { aggregates.Add(a => "ProductID").Count(); })
Is there any way to get around the aggregate problem?