For developers: RadGrid binder
This setions gives an overview of the RadGrid Binder control.
Overview
RadGridBinder is a control which is used to bind the Telerik RadGrid with a data provided by the RESTful WCF service. RadGridBinder represents a bridge between the Telerik RadGrid which supports client side binding and provides rich client side API and Sitefinity CMS WCF services that enables codeless, declarative binding of the grid.
In this first article we are going to examine a simple scenario in which the Telerik RadGrid is bound to the Stores WCF service (used in XML engine documentation).
Since the implementation of the actual service is a different topic which is also covered, we'll assume that the service has been created and is ready to be used.
In this first example we are going to simply bind the collection of the stores to the Telerik RadGrid.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="StoresGrid.aspx.cs" Inherits="StoresGrid" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="sitefinity" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<
head
runat
=
"server"
>
<
title
>Stores with RadGrid client binder</
title
>
</
head
>
<
body
xmlns:sys
=
"javascript:Sys"
xmlns:dataview
=
"javascript:Sys.UI.DataView"
sys:activate
=
"*"
xmlns:code
=
"http://schemas.microsoft.com/aspnet/code"
>
<
form
id
=
"form1"
runat
=
"server"
>
<
asp:ScriptManager
ID
=
"scriptManager1"
runat
=
"server"
>
<
Scripts
>
<
asp:ScriptReference
Name
=
"MicrosoftAjax.js"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjax.js"
/>
<
asp:ScriptReference
ScriptMode
=
"Inherit"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjaxTemplates.js"
/>
<
asp:ScriptReference
ScriptMode
=
"Inherit"
Path
=
"~/Sitefinity/Scripts/MicrosoftAjaxAdoNet.js"
/>
</
Scripts
>
</
asp:ScriptManager
>
<
telerik:RadGrid
id
=
"storesGrid"
runat
=
"server"
allowpaging
=
"True"
AllowSorting
=
"true"
>
<
MasterTableView
PageSize
=
"20"
>
<
Columns
>
<
telerik:GridClientSelectColumn
>
</
telerik:GridClientSelectColumn
>
<
telerik:GridTemplateColumn
HeaderText
=
"Name"
SortExpression
=
"Name"
UniqueName
=
"BinderContainer0"
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
HeaderText
=
"Description"
SortExpression
=
"Description"
UniqueName
=
"BinderContainer1"
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
<
ClientSettings
>
<
Selecting
AllowRowSelect
=
"true"
EnableDragToSelectRows
=
"true"
/>
</
ClientSettings
>
</
telerik:RadGrid
>
<
sitefinity:RadGridBinder
id
=
"resourcesBinder"
runat
=
"server"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"true"
TargetId
=
"storesGrid"
DefaultSortExpression
=
"Name"
DataMembers
=
"Id, Name, Description"
DataKeyNames
=
"Id"
>
<
Containers
>
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Name}}</
strong
>
</
sitefinity:BinderContainer
>
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Description}}</
strong
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:RadGridBinder
>
</
form
>
</
body
>
</
html
>
The sample above was implemented as a standard stand-alone ASP.NET page.
Under assumption that our service will return some data, this page when run, would look something like this:
Binder setup: If you are developing inside of the Sitefinity CMS admin area, it is not necessary to declare ScriptManager control or add anything to the body element, since all this has been implemented on the base Sitefinity CMS admin page.
Let us now explore the above code in more detail.
Example explanation
Declaring the RadGrid control
We start by declaring the Telerik RadGrid control as a regular control.
<
telerik:RadGrid
id
=
"storesGrid"
runat
=
"server"
allowpaging
=
"True"
AllowSorting
=
"true"
>
<
MasterTableView
PageSize
=
"20"
>
<
Columns
>
<
telerik:GridClientSelectColumn
>
</
telerik:GridClientSelectColumn
>
<
telerik:GridTemplateColumn
HeaderText
=
"Name"
SortExpression
=
"Name"
UniqueName
=
"BinderContainer0"
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
HeaderText
=
"Description"
SortExpression
=
"Description"
UniqueName
=
"BinderContainer1"
>
</
telerik:GridTemplateColumn
>
</
Columns
>
</
MasterTableView
>
<
ClientSettings
>
<
Selecting
AllowRowSelect
=
"true"
EnableDragToSelectRows
=
"true"
/>
</
ClientSettings
>
</
telerik:RadGrid
>
We can turn on paging or sorting and customize it as we see fit, relying on the RadGridBinder control to interpret this settings and provide the grid with the correct data.
An important concept that we need to grasp here is the concept of client side templates. The actual data templates we will declare in the RadGridBinder control and in the grid we are merely marking the placeholders for these templates.
Notice how we have two GridTemplateColumn templates with UniqueName properties set to "BinderContainer0" and "BinderContainer1". It is those two controls that will be replaced with actual templates and data on the client once the grid is bound.
Declaring the RadGridBinder control
Now that we have declared the Telerik RadGrid control, we will declare the RadGridBinder control which will be in charge of binding the data from WCF service to the grid. You can think of RadGridBinder control being similar to the data source controls, however, in addition to providing the data, RadGridBinder also performs the actual binding logic.
Let us examine the declaration of the RadGridBinder control:
<
sitefinity:RadGridBinder
id
=
"resourcesBinder"
runat
=
"server"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"true"
TargetId
=
"storesGrid"
DefaultSortExpression
=
"Name"
DataMembers
=
"Id, Name, Description"
DataKeyNames
=
"Id"
>
<
Containers
>
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Name}}</
strong
>
</
sitefinity:BinderContainer
>
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Description}}</
strong
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:RadGridBinder
>
Mapping grid columns to binder containers: Only the columns of type GridTemplateColumn and UniqueName that starts with "BinderContainer" and ends in the index of the binder container will be taken into consideration by RadGridBinder. All other columns will be left as they are.
We notice several properties being declared on this control, so let's explain them chronologically (note that those are not all the properties you can set - take a look at the RadGridBinder reference for a more detailed description).
- ServiceUrl - url of the RESTful WCF service which provides the data for this binder
- BindOnLoad - if true, binder will bind the data to grid as soon as the page loads, othewise a client side method will need to be called (e.g. resourcesBinder.DataBind() - more on client side API of binders can be found in the client side API section).
- TargetId - id of the RadGrid control to which the binder will bind the data
- DefaultSortExpression - the sort expression to be used the very first time data is bound.
- DataMembers - comma delimited list of the properties used by the binder and provided by WCF service. Note that these can be some or all of the properties that have been marked as DataMember on the DataContract supplied by the given service.
- DataKeyNames - comma delimited list of the properties that represent the identity (or primary key) of the given DataContract.
Now that we have covered the properties, all we are left with is the collection of Containers defined by our RadGridBinder. These containers are actually the client side templates (ASP.NET AJAX 4.0 client side templates) that are to be used inside of the RadGrid. If you remember, we've declared two GridTemplateColumn columns in the grid with UniqueName properties set to "BinderContainer0" and "BinderContainer1".
<
telerik:GridTemplateColumn
HeaderText
=
"Name"
SortExpression
=
"Name"
UniqueName
=
"BinderContainer0"
>
</
telerik:GridTemplateColumn
>
<
telerik:GridTemplateColumn
HeaderText
=
"Description"
SortExpression
=
"Description"
UniqueName
=
"BinderContainer1"
>
</
telerik:GridTemplateColumn
>
By doing so, we have instructed the binder to instantiate the first container (or client template) in the column with UniqueName set to "BinderContainer0" (we are using zero based index here) and second binder in the column with UniqueName set to "BinderContainer1". The actual declarations of BinderContainer controls are very simple:
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Name}}</
strong
>
</
sitefinity:BinderContainer
>
<
sitefinity:BinderContainer
runat
=
"server"
>
<
strong
>{{Description}}</
strong
>
</
sitefinity:BinderContainer
>
We simply declare the binder container, place the html markup inside of it and we are done. In the places where we want the actual data to appear, we use the following syntax: {{PropertyName}} which is roughly equivalent to the server side Eval("PropertyName") function. And we are done.