The particular implementation above is to be taken only as an example. Namely, there is nothing preventing us to open the store details as soon as the different store is selected from the drop down list - we do not need an "Open" button.
<%@ 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
>
<
input
type
=
"button"
onclick
=
"OpenStore();"
value
=
"Open"
/>
<
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
value
=
"{{Id}}"
>{{Name}}</
option
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:GenericCollectionBinder
>
<
div
id
=
"storeForm"
runat
=
"server"
>
</
div
>
<
sitefinity:FormBinder
ID
=
"storeFormBinder"
runat
=
"server"
TargetId
=
"storeForm"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"false"
DataKeyNames
=
"Id"
DataMembers
=
"Id, Name, Description"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer2"
runat
=
"server"
>
<
fieldset
>
<
legend
>Store info:</
legend
>
<
ul
>
<
li
>
Store name: {{Name}}
</
li
>
<
li
>
Store description: {{Description}}
</
li
>
</
ul
>
</
fieldset
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:FormBinder
>
<
script
type
=
"text/javascript"
>
function OpenStore() {
var storeId = $('#' + '<%= storesDropDown.ClientID %>').val();
var storeFormBinder = $find('<%= storeFormBinder.ClientID %>');
storeFormBinder.get_globalDataKeys()["Id"] = storeId;
storeFormBinder.DataBind();
}
</
script
>
</
body
>
</
html
>
The sample above was implemented as a standard stand-alone ASP.NET page.
Since we the GenericCollection binder is described in different article, we will skip that part and go straight to the FormBinder.
Declaring the form placeholder
When working with the FormBinder, the same pattern as with the other binders apply. First what we need to do is declare the element (it has to be a server side control) where we wish our form to be instantiated. We have done so by declaring the storeForm HtmlGenericControl:
<
div
id
=
"storeForm"
runat
=
"server"
>
</
div
>
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.
Once we have declared the form placeholder, we can move on to declaring the FormBinder.
Declaring the FormBinder
FormBinder, just as any other Sitefinity CMS client binder, inherits from the base ClientBinder class, so it's declaration looks very similar to other client binder controls.
<
sitefinity:FormBinder
ID
=
"storeFormBinder"
runat
=
"server"
TargetId
=
"storeForm"
ServiceUrl
=
"~/Sitefinity/Services/Commerce/Stores.svc"
BindOnLoad
=
"false"
DataKeyNames
=
"Id"
DataMembers
=
"Id, Name, Description"
>
<
Containers
>
<
sitefinity:BinderContainer
ID
=
"BinderContainer2"
runat
=
"server"
>
<
fieldset
>
<
legend
>Store info:</
legend
>
<
ul
>
<
li
>
Store name: {{Name}}
</
li
>
<
li
>
Store description: {{Description}}
</
li
>
</
ul
>
</
fieldset
>
</
sitefinity:BinderContainer
>
</
Containers
>
</
sitefinity:FormBinder
>
Let us first explain the properties of the FormBinder control that we have declared.
- TargetId - id of the server side control in which the form 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.
Notice, that we have set the BindOnLoad property to false, which means that FormBinder will NOT bind the form to data when the page loads. The reason for this is that we do not know the key of the object (Store) to which we wish to bind the form. Therefore, we will bind the form after the user selects one of the stores from the drop down list and clicks on the "Open" button.
Notice, that we have specified the "onClick" function on the Open button to be "OpenStore();":
<
input
type
=
"button"
onclick
=
"OpenStore();"
value
=
"Open"
/>
Then, if we proceed to examine the implementation of the JavaScript function OpenStore we will find following code:
function
OpenStore() {
var
storeId = $(
'#'
+
'<%= storesDropDown.ClientID %>'
).val();
var
storeFormBinder = $find(
'<%= storeFormBinder.ClientID %>'
);
storeFormBinder.get_globalDataKeys()[
"Id"
] = storeId;
storeFormBinder.DataBind();
}
In the very first line, we are simply using
jQuery javascript framework (which is always present when we use client binder controls, so we can safely use it without referencing it) to obtain the id of the store selected in the drop down list.
In the second line, we are obtaining the reference to the client side form binder object. It is important to note that all client binder controls implement IScriptControl interface which makes them server side control with available client side components and client side API.
The client binder components come with a rich client side API, which we explain Client Side API Reference of the manual. In this article, we will not go into details, but rather explain only the two members that we are using.
First we are setting the Id key of the form binder by accessing the globalDataKeys collection and we set it to the id of the store selected in the drop down. Client binders have two collections which work with the identity (or primary key) of the objects. When one is working with the collection of data items dataKeys property (which is index property, so we can access it like dataKeys[3]) holds the dataKey values for all the items of the collection. On the other hand, globalDataKeys will set the value of the identity to the whole collection (this becomes very useful when working with composite primary keys). We have a whole topic dedicated on primary keys and identity management with client binders, so we will not go into more details here.
Once we have set the value of the globalDataKey, all we need to do is call DataBind() method on the client binder.
NOTE: Consistency of the DataBind function: All client binders implement DataBind() method, so you can safely call it on any type of a client binder.
NOTE: Getting the client reference of the binder component: To get the reference to the client side component of a client binder, all we need to do is call the $find function of the
ASP.NET Ajax framework and pass the client id of the server side binder control to it as a parameter. Once we obtain the reference to the client side binder component we can use the client binder client side API to work with the components.