For developers: Generic collection binder
This section contains information about the Generic Collection binder.
Overview
Generic collection binder is a client binder similar in its usage to For developers: RadGrid binder (namely, it binds a collection of items), however, unlike RadGrid binder, it can bind items to any kind of element. You can think of Generic Collection binder in terms of client side repeater.
The simplest possible explanation of this binder would be: it instantiates given number of templates in a target element. In this article, we are going to see how to use Generic Collection binder to bind a list of stores (we are using the same service we've used to demonstrate binding of Telerik RadGrid) to a html SELECT element.
Under assumption that you've got yourself familiar with the implementation of WCF RESTful services for Sitefinity CMS (it is in this manual) we will skip the explanation of the service itself.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Stores.aspx.cs" Inherits="Stores" %>
<%@ 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 Generic Collection 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
>
<
select
id
=
"storesDropDown"
runat
=
"server"
>
</
select
>
<
sitefinity:GenericCollectionBinder
id
=
"storesBinder"
runat
=
"server"
TargetId
=
"storesDropDown"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"true"
DataKeyNames
=
"Id"
DataMembers
=
"Name, Id"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer1"
runat
=
"server"
RenderContainer
=
"false"
TemplateHolderTag
=
"SELECT"
>
<
option
sys:value
=
"{{Id}}"
>{{Name}}</
option
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:GenericCollectionBinder
>
</
body
>
</
html
>
Declaring the collection element
There is really not much to declaring the collection element. In our sample we have used SELECT element (note that it has to be a server side control, thus the runat="server" property, since the TargetID property of the binders is always looking for the id of the server side control).
<
sitefinity:GenericCollectionBinder
id
=
"storesBinder"
runat
=
"server"
TargetId
=
"storesDropDown"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"true"
DataKeyNames
=
"Id"
DataMembers
=
"Name, Id"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer1"
runat
=
"server"
RenderContainer
=
"false"
TemplateHolderTag
=
"SELECT"
>
<
option
sys:value
=
"{{Id}}"
>{{Name}}</
option
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:GenericCollectionBinder
>
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.
First, we have set the properties of the binder:
- TargetId - id of the collection element (must be a server side control) in which the collection items ought to be instantiated.
- ServiceUrl - url of the WCF service which serves as a data provider for our control
- BindOnLoad - if true, the binder will load data as soon as the page loads, otherwise we will need to use client binders client side API and call DataBind() method.
- DataKeyNames - comma delimited list of all properties composing an identity (or primary key) of the object to which we are binding (in our case Store).
- DataMembers - comma delimited list of all properties of the object to which we are binding that we will use in our containers.
Finally, now that we have declared the properties of the binder, we are declaring the one BinderContainer (note that multiple Binder controls are supported only by RadGrid binder, due to the fact that we are working with columns there). Notice how we are using <OPTION> element as part of our template, which will ensure that when collection is bound, the instantiated items inside of our <SELECT> element will be <OPTION> elements. Similarily, if our collection element was an unordered list (<UL>), in the binder template we would have a <LI> element instead of the <OPTION> element.
Since ASP.NET AJAX 4.0 client templates are rendered on the page (though hidden), in order to ensure that our page validates, we are specifying the TemplateHolderTag to be SELECT tag. This way, our template will be a valid OPTION element inside of a SELECT element.
And finally, we are using the following syntax to mark the places where we want to bind data item properties: {{PropertyName}} which is very similar to the server side Eval("PropertyName") syntax.