Vertical Grid Custom Data Binding
- 8 minutes to read
The VerticalGrid supports custom data binding that allows you to provide the extension with data manually. In this custom data binding mode, you have full control of and responsibility for populating the VerticalGrid with the required data each time the extension requests it.
Note
The Custom Data Binding mode was specially designed for working with a large data volume and handling all data shaping operations manually (e.g., it is impossible to use the built-in Linq/Entity Framework capabilities).
If there are no strict requirements for using Custom Data Binding, using one of the following data binding modes is recommended.
- Regular binding mode - designed for small data sources. Refer to the following topics to learn more: Binding to Data via Entity Framework (Code First) and Binding to Data via Entity Framework or LINQ to SQL (Database First).
- Database Server Mode - designed for large data sources (See demo: Data Binding to Large Database, documentation: Binding to Large Data (Database Server Mode)).
In brief, this mode requires that you manually populate a VerticalGrid-specific view model with the portion of data that needs to be currently displayed within the extension. You can accomplish this by performing the following steps.
Define Handling Actions
In addition to a standard handling Action defined using the GridSettingsBase.CallbackRouteValues, use the VerticalGridSettings.CustomBindingRouteValuesCollection to specify additional Actions to handle all or specific data operations (paging, filtering, sorting), depending on which functionality is used in your VerticalGrid. Data operations are identified by the VerticalGridOperationType enumeration values.
Obtain/Update VerticalGrid State
In Actions, use the static VerticalGridExtension.GetViewModel method to obtain the extension’s view model, which is a specific VerticalGridModel object designed to maintain the VerticalGrid state and provide a means to populate itself with data. By default, the view model obtained within Actions contains the previous state of the VerticalGrid. If required, update this state with the state information that relates the processed operation and is automatically passed to an Action as a parameter. (For instance, this state can be a row state (VerticalGridRowState) that contains information on which row is sorted and in which direction/order, or a pager state (VerticalGridPagerState) that determines which page is selected.)
Delegate Model Population
Within a Controller, use the VerticalGrid view model that contains the up-to-date VerticalGrid state and call its VerticalGridModel.ProcessCustomBinding method to delegate the implementation of a model population to certain Model-layer functions specified with method parameters.
Implement Model Population
At the Model layer, implement certain delegates, which are pointed to by the VerticalGridModel.ProcessCustomBinding method’s parameters to populate the VerticalGrid view model with a portion of the currently required data.
Bind the VerticalGrid to the Populated Model
In a Controller, pass the populated view model object as a Model to the VerticalGrid’s Partial View. In the Partial View, bind the extension to the passed Model by using the VerticalGridExtension.BindToCustomData method.
Note
When implementing the VerticalGrid’s custom data binding, the DevExpressEditorsBinder must be used instead of the default model binder to correctly transfer values from DevExpress editors back to the corresponding data model fields. See the Binding to Model section in the Binding Data Editors to Data topic for more details on how to specify DevExpressEditorsBinder as a model binder.
These steps are described in greater detail below.
Define Handling Actions
To associate a VerticalGrid data operation type with a handling Action method, populate the extension’s specific route values collection available using the VerticalGridSettings.CustomBindingRouteValuesCollection property. Register each data operation that you need to handle by adding a specific item to the collection. Within an item, identify a data operation and specify a handling method by providing its Controller and Action names.
Partial View Code:
@Html.DevExpress().VerticalGrid(
settings => {
settings.Name = "verticalGrid";
//Specify an Action to handle standard callback requests (including population of the VerticalGrid with data on the first load)
settings.CallbackRouteValues = new { Controller = "MyController", Action = "MyVerticalGridPartial" };
//Specify Actions to handle certain data operations - in this sample, these operations are paging, sorting and filtering
settings.CustomBindingRouteValuesCollection.Add(
VerticalGridOperationType.Paging,
new { Controller = "MyController", Action = "CustomBindingPagingAction" }
);
settings.CustomBindingRouteValuesCollection.Add(
VerticalGridOperationType.Sorting,
new { Controller = "MyController", Action = "CustomBindingSortingAction" }
);
settings.CustomBindingRouteValuesCollection.Add(
VerticalGridOperationType.Filtering,
new { Controller = "MyController", Action = "CustomBindingFilteringAction" }
);
...
Refer to the Action Types and Passed Parameters topic to learn more about available data operation types.
Obtain/Update VerticalGrid State
In each specified Action, you can obtain both the previous state of the VerticalGrid (the state the VerticalGrid had before an end-user performed the currently processed data operation) and the information (state) specific to the currently processed operation (for instance, information about the applied paging or sorted row). The VerticalGrid’s previous state can be obtained as a VerticalGrid view model object (VerticalGridModel) by making a call to the static VerticalGridExtension.GetViewModel method. The currently processed data operation’s state is automatically passed to each Action as its parameter(s). You can update the VerticalGrid view model object, maintaining the previous VerticalGrid state with the state of the currently processed operation to update the VerticalGrid state. Then, the updated VerticalGrid view model should be processed to populate it with the required data (see the next item for details).
Controller Code:
public partial class MyController: Controller {
public ActionResult MyVerticalGrid() {
return View("MyVerticalGrid");
}
//Standard VerticalGrid callback requests
public ActionResult MyVerticalGridPartial() {
var viewModel = VerticalGridExtension.GetViewModel("verticalGrid");
if(viewModel == null)
//Initialize the VerticalGrid state on the first load
viewModel = CreateVerticalGridModel();
return MyCustomBindingCore(viewModel);
}
//Paging operation requests
public ActionResult MyPagingAction(VerticalGridPagerState pager) {
var viewModel = VerticalGridExtension.GetViewModel("verticalGrid");
viewModel.ApplyPagingState(pager); //Update the VerticalGrid state with the processed paging state
return MyCustomBindingCore(viewModel);
}
//Sorting operation requests
public ActionResult MySortingAction(VerticalGridRowState row, bool reset) {
var viewModel = VerticalGridExtension.GetViewModel("verticalGrid");
viewModel.ApplySortingState(row, reset); //Update the VerticalGrid state with the processed sorting state
return MyCustomBindingCore(viewModel);
}
PartialViewResult MyCustomBindingCore(VerticalGridModel viewModel) {
... //Some code to delegate model population to Model-layer functions (see the next item)
return PartialView("MyVerticalGridPartial", viewModel);
}
static VerticalGridModel CreateVerticalGridModel() {
var viewModel = new VerticalGridModel();
viewModel.KeyFieldName = "ID";
viewModel.Rows.Add("From");
viewModel.Rows.Add("Subject");
viewModel.Rows.Add("Sent");
viewModel.Rows.Add("Size");
viewModel.Rows.Add("HasAttachment");
return viewModel;
}
}
Refer to the Action Types and Passed Parameters topic to learn more on operation-specific parameters passed to handling Actions automatically.
See the Methods to Update the VerticalGrid State in Actions topic for a list of methods the VerticalGridModel exposes to update the VerticalGrid state.
Delegate Model Population
Given the VerticalGrid view model, call its VerticalGridModel.ProcessCustomBinding method to delegate the implementation of a model population to certain Model-layer functions specified with method parameters. The VerticalGridModel.ProcessCustomBinding method has several overloads. You can select one depending on which data operations you need to handle.
Controller Code:
public partial class MyController: Controller {
...
PartialViewResult MyCustomBindingCore(VerticalGridModel verticalGridModel) {
//Delegate implementation of the functions that are always required for custom binding
verticalGridModel.ProcessCustomBinding(
MyBindingHandlers.MyGetDataColumnCount, //Function to return the total number of data columns in a model
MyBindingHandlers.MyGetData //Function to return data columns requested by the VerticalGrid
);
return PartialView("MyVerticalGridPartial", verticalGridModel);
}
}
Sample Model Code:
...
public static class MyBindingHandlers {
static IQueryable Model { get { return LargeDatabaseDataProvider.Emails; } }
public static void MyGetDataColumnsCount(VerticalGridCustomBindingGetDataColumnCountArgs e) {
... //Code for the delegate method implementation
}
public static void MyGetData(VerticalGridCustomBindingGetDataArgs e) {
... //Code for the delegate method implementation
}
...
}
...
Refer to the ProcessCustomBinding - Available Binding Delegates topic to learn more about the VerticalGridModel.ProcessCustomBinding method.
Implement Model Population
At the Model layer, provide implementation for the specified method delegates according to your application needs and domain layer logic. Use arguments available through the e parameter of method delegates to obtain operation-related information and to supply the model with the required data.
Model Code:
...
public static class MyBindingHandlers {
static IQueryable Model { get { return LargeDatabaseDataProvider.Emails; } }
public static void MyGetDataColumnCount(VerticalGridCustomBindingGetDataColumnCountArgs e) {
e.DataColumnCount = Model.Count(); //Return the total count of data columns in your model (taking into account the applied filtering, if any)
}
public static void MyGetData(VerticalGridCustomBindingGetDataArgs e) {
e.Data = Model
.ApplySorting(e.State.SortedRows) //Your function to implement sorting of a model
.Skip(e.StartDataColumnIndex) //Position on the first required data column
.Take(e.DataColumnCount); //Get the number of currently required data columns (columns of the current page)
}
...
}
...
Refer to the Implementation of Typed Method Delegates topic to learn more about the available arguments and the implementation of method delegates.
Bind the VerticalGrid to the Populated Model
The resulting populated VerticalGrid view model object should be returned as a Model to a Partial View that contains the VerticalGrid markup. To bind the VerticalGrid to this view model, use the VerticalGridExtension.BindToCustomData method within the extension’s Partial View.
Controller Code:
public partial class MyController: Controller {
...
public ActionResult MyVerticalGridPartial() {
...
return MyCustomBindingCore(viewModel);
}
public ActionResult MyPagingAction(VerticalGridPagerState pager) {
...
return MyCustomBindingCore(viewModel);
}
public ActionResult MySortingAction(VerticalGridRowState row, bool reset) {
...
return MyCustomBindingCore(viewModel);
}
PartialViewResult MyCustomBindingCore(VerticalGridModel viewModel) {
...
return PartialView("MyVerticalGridPartial", viewModel);
}
...
}
Partial View Code:
@Html.DevExpress().VerticalGrid(
settings => {
settings.Name = "verticalGrid";
...
}).BindToCustomData(Model).GetHtml()