Example E4394
Visible to All Users

Grid View for ASP.NET MVC - How to implement a simple custom binding scenario

This example demonstrates how to implement a simple custom binding scenario for the GridView extension and handle sorting and paging operations in the corresponding Action methods.

You can modify this approach to use it with any data source object that implements the IQueryable interface.

Implementation details

Custom data binding requires that the DevExpressEditorsBinder is used instead of the default model binder to correctly transfer values from DevExpress editors back to the corresponding data model fields.
Assign DevExpressEditorsBinder to the ModelBinders.Binders.DefaultBinder property in the Global.asax file to override the default model binder.

C#
ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder();

Grid partial view

The CustomBindingRouteValuesCollection property allows you to assign particular handling Actions for four data operations - paging, sorting, grouping, and filtering. In this example, the property specifies custom routing for sorting and paging operations.

Razor
settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Sorting, new { Controller = "Home", Action = "GridViewSortingAction" } ); settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Paging, new { Controller = "Home", Action = "GridViewPagingAction" } );

The CallbackRouteValues property specifies the action that handles all other (standard) grid callbacks.

Razor
settings.CallbackRouteValues = new { Controller = "Home", Action = "GridViewPartial" };

Controller

Action methods update the GridViewModel object with the information from the performed operation. The ProcessCustomBinding method delegates the binding implementation to specific model-layer methods pointed by the method's parameters.

C#
public ActionResult GridViewPartial() { var viewModel = GridViewExtension.GetViewModel("GridView"); if (viewModel == null) viewModel = CreateGridViewModel(); return GridCustomActionCore(viewModel); } public ActionResult GridViewSortingAction(GridViewColumnState column, bool reset) { var viewModel = GridViewExtension.GetViewModel("GridView"); viewModel.SortBy(column, reset); return GridCustomActionCore(viewModel); } public ActionResult GridViewPagingAction(GridViewPagerState pager) { var viewModel = GridViewExtension.GetViewModel("GridView"); viewModel.Pager.Assign(pager); return GridCustomActionCore(viewModel); }

Model

The specified delegates populate the Grid View model with data. To bind the Grid to your particular model object, modify the following code line:

C#
static IQueryable Model { get { return NorthwindDataProvider.GetCustomers(); } }

The Grid View model object is passed from the Controller to the grid's Partial View as a Model. In the Partial View, the BindToCustomData method binds the grid to the Model.

Files to Review

Documentation

More Examples

Example Code

Sample/Controllers/HomeController.cs(vb)
C#
using DevExpress.Web.Mvc; using Sample.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Sample.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } public ActionResult GridViewPartial() { var viewModel = GridViewExtension.GetViewModel("GridView"); if (viewModel == null) viewModel = CreateGridViewModel(); return GridCustomActionCore(viewModel); } public ActionResult GridViewSortingAction(GridViewColumnState column, bool reset) { var viewModel = GridViewExtension.GetViewModel("GridView"); viewModel.SortBy(column, reset); return GridCustomActionCore(viewModel); } public ActionResult GridViewPagingAction(GridViewPagerState pager) { var viewModel = GridViewExtension.GetViewModel("GridView"); viewModel.Pager.Assign(pager); return GridCustomActionCore(viewModel); } public ActionResult GridCustomActionCore(GridViewModel gridViewModel) { gridViewModel.ProcessCustomBinding( CustomBindingHandlers.GetDataRowCount, CustomBindingHandlers.GetData ); return PartialView("GridViewPartial", gridViewModel); } static GridViewModel CreateGridViewModel() { var viewModel = new GridViewModel(); viewModel.KeyFieldName = "CustomerID"; viewModel.Columns.Add("ContactName"); viewModel.Columns.Add("CompanyName"); viewModel.Columns.Add("ContactTitle"); viewModel.Columns.Add("City"); viewModel.Columns.Add("Phone"); viewModel.Pager.PageSize = 20; return viewModel; } } }
Sample/Global.asax.cs(vb)
C#
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; namespace Sample { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder(); DevExpress.Web.ASPxWebControl.CallbackError += Application_Error; } protected void Application_Error(object sender, EventArgs e) { Exception exception = System.Web.HttpContext.Current.Server.GetLastError(); //TODO: Handle Exception } } }
Sample/Models/CustomBindingModel.cs(vb)
C#
using System; using System.Collections.Generic; using System.Linq; using DevExpress.Data; using DevExpress.Data.Filtering; using DevExpress.Data.Linq; using DevExpress.Data.Linq.Helpers; using DevExpress.Web.Mvc; namespace Sample.Models { public static class CustomBindingHandlers { static IQueryable Model { get { return NorthwindDataProvider.GetCustomers(); } } public static void GetDataRowCount(GridViewCustomBindingGetDataRowCountArgs e) { e.DataRowCount = Model.Count(); } public static void GetData(GridViewCustomBindingGetDataArgs e) { e.Data = Model .ApplySorting(e.State.SortedColumns) .Skip(e.StartDataRowIndex) .Take(e.DataRowCount); } } public static class GridViewCustomOperationDataHelper { static ICriteriaToExpressionConverter CreateConverter(Type queryType) { return new CriteriaToEFExpressionConverter(queryType); } public static IQueryable Select(this IQueryable query, string fieldName) { return query.MakeSelect(CreateConverter(query.Provider.GetType()), new OperandProperty(fieldName)); } public static IQueryable ApplySorting(this IQueryable query, IEnumerable<GridViewColumnState> sortedColumns) { foreach(GridViewColumnState column in sortedColumns) query = ApplySorting(query, column.FieldName, column.SortOrder); return query; } public static IQueryable ApplySorting(this IQueryable query, string fieldName, ColumnSortOrder order) { return query.MakeOrderBy(CreateConverter(query.Provider.GetType()), new ServerModeOrderDescriptor(new OperandProperty(fieldName), order == ColumnSortOrder.Descending)); } public static IQueryable ApplyFilter(this IQueryable query, string filterExpression) { return query.AppendWhere(CreateConverter(query.Provider.GetType()), CriteriaOperator.Parse(filterExpression)); } } }
Sample/Models/Northwind.cs(vb)
C#
using System.Linq; using System.Web; namespace Sample.Models { public static class NorthwindDataProvider { const string NorthwindDataContextKey = "DXNorthwindDataContext"; public static NorthwindDataContext DB { get { if(HttpContext.Current.Items[NorthwindDataContextKey] == null) HttpContext.Current.Items[NorthwindDataContextKey] = new NorthwindDataContext(); return (NorthwindDataContext)HttpContext.Current.Items[NorthwindDataContextKey]; } } public static IQueryable<Customer> GetCustomers() { return DB.Customers; } } }
Sample/Views/Home/GridViewPartial.cshtml
Razor
@Html.DevExpress().GridView( settings => { settings.Name = "GridView"; settings.CallbackRouteValues = new { Controller = "Home", Action = "GridViewPartial" }; settings.Width = System.Web.UI.WebControls.Unit.Percentage(100); settings.KeyFieldName = "CustomerID"; settings.Columns.Add("ContactName"); settings.Columns.Add("CompanyName"); settings.Columns.Add("ContactTitle"); settings.Columns.Add("City"); settings.Columns.Add("Phone"); settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Sorting, new { Controller = "Home", Action = "GridViewSortingAction" } ); settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Paging, new { Controller = "Home", Action = "GridViewPagingAction" } ); }).BindToCustomData(Model).GetHtml()
Sample/Views/Home/GridViewPartial.vbhtml
Code
@Html.DevExpress().GridView(Sub(settings) settings.Name = "GridView" settings.CallbackRouteValues = New With { .Controller = "Home", .Action = "GridViewPartial" } settings.Width = Unit.Percentage(100) settings.KeyFieldName = "CustomerID" settings.Columns.Add("ContactName") settings.Columns.Add("CompanyName") settings.Columns.Add("ContactTitle") settings.Columns.Add("City") settings.Columns.Add("Phone") settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Sorting, New With { .Controller = "Home", .Action = "GridViewSortingAction" } ) settings.CustomBindingRouteValuesCollection.Add( GridViewOperationType.Paging, New With { .Controller = "Home", .Action = "GridViewPagingAction" } ) End Sub).BindToCustomData(Model).GetHtml()
Sample/Views/Home/Index.cshtml
Razor
@Html.Action("GridViewPartial")
Sample/Views/Home/Index.vbhtml
Code
@Html.Action("GridViewPartial")
Sample/Views/Shared/_Layout.cshtml
Razor
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>@ViewBag.Title</title> @Html.DevExpress().GetStyleSheets( new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout }, new StyleSheet { ExtensionSuite = ExtensionSuite.Editors }, new StyleSheet { ExtensionSuite = ExtensionSuite.GridView } ) @Html.DevExpress().GetScripts( new Script { ExtensionSuite = ExtensionSuite.NavigationAndLayout }, new Script { ExtensionSuite = ExtensionSuite.Editors }, new Script { ExtensionSuite = ExtensionSuite.GridView } ) </head> <body> @RenderBody() </body> </html>
Sample/Views/Shared/_Layout.vbhtml
Code
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>@ViewData("Title")</title> @Html.DevExpress().GetStyleSheets( New StyleSheet With {.ExtensionSuite = ExtensionSuite.NavigationAndLayout }, New StyleSheet With {.ExtensionSuite = ExtensionSuite.Editors }, New StyleSheet With {.ExtensionSuite = ExtensionSuite.GridView } ) @Html.DevExpress().GetScripts( New Script With {.ExtensionSuite = ExtensionSuite.NavigationAndLayout }, New Script With {.ExtensionSuite = ExtensionSuite.Editors }, New Script With {.ExtensionSuite = ExtensionSuite.GridView } ) </head> <body> @RenderBody() </body> </html>

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.