[This post is part of the developer's manual preview published on this blog. You can find temporary TOC here.]
Traditionally, grid controls have been bound on the server, which meant that grid would take certain data and replace the templates of its grid columns on the server side. This, of course, meant that for example when we would sort the grid or page through grid items, we would have caused a postback.
When we are talking about client side data binding for Generic Content based modules, we are talking about the RadGrid control which lists all the content items of a given module.
When building a Generic Content module and you wish to implement client side data binding you can follow these steps to achieve it quickly.
Sometimes you will need to access the properties defined in the View in the template. For example, we will need the name of the provider to call the web service (if you copy and paste one of the predefined templates, you don’t actually have to worry about provider name - we are using it here only as an example). In products module, ProductsItemListView (actually it’s base ContentItemList) defines property ProviderName in following manner:
In order to access the value of this property in our template, we can use following syntax in our template:
In case you are using Sitefinity template parser (your template is embedded or your external template has an extension different than .ascx) you do not need to cast the Parent.Parent object. However, if you are using standard ASP.NET template parser (you are using external template which ends with .ascx extension) you will need to cast the Parent.Parent object to its actual type. For example, in products module this would be:
*** END NOTE ***
One of the improvements introduced in Sitefinity 3.6 have been very fast and responsive grids in Generic Content modules. We have switched from standard ASP.NET GridView controls to the feature rich Telerik RadGrid control and took the advantage of the built-in client side data binding mechanism.
While, client side data binding in general is still not as trivial as it should be, we have provided few enhancements that will allow you to take advantage of this attractive technique with minimal effort.
What is client side data binding
Traditionally, grid controls have been bound on the server, which meant that grid would take certain data and replace the templates of its grid columns on the server side. This, of course, meant that for example when we would sort the grid or page through grid items, we would have caused a postback.
Client side data binding of RadGrid allows us to use very similar syntax and approach of traditional data binding, but however, the actual binding happens on the client. This results in a tremendously faster and more responsive user experience. Namely, since there is no postback, when we page through items or sort items - only the values of columns get replaced and do so on the client.
In this topic we will examine how has this approach been adjusted to Generic Content grids and how can you take advantage of it to provide fast and responsive grids in your Generic Content based modules.
Client side data binding for the Generic Content based modules
When we are talking about client side data binding for Generic Content based modules, we are talking about the RadGrid control which lists all the content items of a given module.
When binding the grid on the client side, you will actually work against lightweight version of the CmsContentBase object (Generic Content item). You can bind to following members of the SimpleContent object:
- ID - Guid
Id of the content item object - Status - string
Status of the content item, such as published, draft and so on - Comments - int
Number of comments posted on the content item - IsLocked - bool
Returns true if content item is locked by another user, otherwise false - Modifier - string
User name of the user who was the last to modify the content - IsDisabled - bool
Returns true if the content item is disabled for the current user (e.g. insufficient permissions, workflow and so on) - IsOwner - bool
Returns true if the current user is also the owner of the content, otherwise false - DateCreated - DateTime
Returns the date and time of the content creation - DateModified - DateTime
Returns the date and time of the last modification of the content - AbsoluteUrl - string
Used primarily with Images & Documents module. Returns the absolute url of the conten item - ThumbnailUrl - string
Used primarily with Images & Documents module. Returns the url of the thumbnail if one exists - Owner - string
Returns the user name of the user that created this content item - MimeType - string
Used primarily with Images & Documents module. Returns the Mime Type of the content item - All metafields
Any meta field defined for the provider of the Generic Content module can be bound to
Step by step walkthrough of defining client side grid columns
When building a Generic Content module and you wish to implement client side data binding you can follow these steps to achieve it quickly.
- Create a template for the item list view - the view that will display list of content items. The simplest way is to copy and paste one of the embedded templates or use the ProductItemList.ascx template that comes with the sample Products module.
- Second step is to define the grid columns. Locate the RadGrid control and define GridTemplateColumns for every column you wish to display in the grid. The process is very similar to what you would do if you are to structure a traditional grid and bind it on the server. There are only two important steps here:
- Use only GridTemplateColumn for your columns
- Define the meaningful UniqueName property for each column
Notice that we are not defining any content here or data fields. The actual binding will take place in the next step. - Map GridColumns to ClientTemplates. Locate the ClientTemplatesHolder control and for each column you have defined in in the grid create a client template.
SAMPLE CLIENT TEMPLATE:
<telerik:ClientTemplate Name="Price" runat="server"> {#MetaFields.Price#} </telerik:ClientTemplate> - If you are binding to a property, than you should use {#PropertyName#}. An example of this approach would be {#Status#}
- If you are binding to a meta field value, than you should use {#MetaFields.MetaFieldKey#}. An example of this approach is {#MetaFields.Price#}
- Since the whole idea of client side data binding is to increase the responsiveness of the grid control, it is our goal to keep the data transfer to the minimum. When binding on the client side, server will send you only the required meta fields and not all of them. Required meta fields are the ones you will use in your ClientTemplates as it was described in previous step. In order to define required metafields, locate the JavaScript DataBindGrid function and inside of it find requiredMetaFields array. In products module this array looks like this:
var requiredMetaFields = ['Name', 'Price', 'SKU'];
SAMPLE COLUMN:
<telerik:GridTemplateColumn |
UniqueName="Price" |
SortExpression="Price" |
HeaderText="<%$ Resources:Price %>"> |
</telerik:GridTemplateColumn> |
After you have finished these three steps, your client side data bound grid is ready.
Accessing View properties in the template
Sometimes you will need to access the properties defined in the View in the template. For example, we will need the name of the provider to call the web service (if you copy and paste one of the predefined templates, you don’t actually have to worry about provider name - we are using it here only as an example). In products module, ProductsItemListView (actually it’s base ContentItemList) defines property ProviderName in following manner:
/// <summary> |
/// Gets the name of the current content data provider. |
/// </summary> |
public virtual string ProviderName |
{ |
get |
{ |
return this.Manager.Provider.Name; |
} |
} |
var dataProviderName = "<%= Parent.Parent.ProviderName %>"; |
*** BEGIN NOTE ***
In case you are using Sitefinity template parser (your template is embedded or your external template has an extension different than .ascx) you do not need to cast the Parent.Parent object. However, if you are using standard ASP.NET template parser (you are using external template which ends with .ascx extension) you will need to cast the Parent.Parent object to its actual type. For example, in products module this would be:
var dataProviderName = "<%= ((Telerik.Samples.Products.WebControls.Admin.Products.ProductsItemListView)Parent.Parent).ProviderName %>"; |