Things for now become more and more interesting. Oh, to
display the contents of a RSS channel you just need to click one item in the
ListView and let the right-side Accordion control exhibit the related details.
This is quite right from the user's point of view, but I, as a programmer,
spent plenty of time tackling this problem and my solution is sure to wait to be
improved by many ASP.NET Ajax gurus. Let me introduce my ugly solution to you.
Getting the Contents of a Channel over the Network
1. Something about the ListView control
As far as the ASP.NET AJAX client-side "advanced"
ListView control is further examined, we can see it is far from mature. By
researching into the source file PreviewScript.js that is shipped with ASP.NET
AJAX CTP version, we find that there are not abundant properties, methods, and
events in its descriptor block (note: only things within
this block can be used via xml-script mode) for us to use in the declarative
xml-script programming to control ListView. The following Listing gives this
block's definition.
Listing 8
Sys.Preview.UI.Data.ListView.descriptor = {
properties: [ { name: 'alternatingItemCssClass', type: String },
{ name: 'layoutTemplate', type: Sys.Preview.UI.ITemplate },
{ name: 'itemCssClass', type: String },
{ name: 'itemTemplate', type: Sys.Preview.UI.ITemplate },
{ name: 'itemTemplateParentElementId', type: String },
{ name: 'selectedItemCssClass', type: String },
{ name: 'separatorCssClass', type: String },
{ name: 'separatorTemplate', type: Sys.Preview.UI.ITemplate },
{ name: 'emptyTemplate', type: Sys.Preview.UI.ITemplate } ],
events: [ {name: 'renderComplete'} ]
}
Only several properties and one event are provided. As for
methods to use, we have to resort to those of its parent class DataControl (merely in support of a few methods). Therefore,
to control the item (i.e. record) click event, we have to further research into
its prototype block and fall back on the blasted JavaScript
programming.
2. Adding click event to ListView via
JavaScript
Let us list all the source code associated with the above
target.
Listing 9
<script language="javascript" type="text/javascript">
var g_RSSNameList;
function pageLoad(sender, args) {
g_RSSNameList=$find('RSSNameList');
$addHandler($get('RSSNameList'), 'click', clickRowHandler);
}
function clickRowHandler(ev)
{
var s = ev.target;
while (s && (typeof(s.dataIndex) === 'undefined')) {
s = s.parentNode;
}
if (s) {
var idx = s.dataIndex;
//call the server-side method in relation to Server side
//dummy Button 'dummySrvBtn'
<span lang=PT>var btn ='<%=dummySrvBtn.ClientID%>';</span>
<span lang=PT>var txt='<%=txtRssUrl2.ClientID%>';</span>
<span lang=PT>document.getElementById(txt).value=s.lastChild.innerText; </span>
__doPostBack(btn,'');
}
}
......(omitted)
function pageUnload() {
//dispose the event handler
if (clickRowHandler)
$removeHandler($get('RSSNameList'), "click",clickRowHandler);
clickRowHandler=null;
}
Here, we first use the global method $addHandler
to attach the event handler clickRowHandler to the "click"
event of ListView RSSNameList. Next, we start the event
handler programming. At the very beginning the property ev.target
is pointing to ListView RSSNameList. When the control
flows to the if conditional sentence the variable s points to searchResults_itemTemplate
(where the database record lies). OK, for now we can get the current value of
the record index using variable idx and get any field (we
are only interested in field Rss_URL which corresponds
to the last field) value we want to fetch.
Things now become more complex; how can we dynamically
assign the current RSS url to RssDataSource, the third-party server-side data
source control? My ugly solution to this is to resort to the method "__doPostBack."
According to my analysis, we cannot dynamically bind RssDataSource
to Acccordion in some Web Service method. Thus, we have
to seek anywhere else— the CodeFile AjaxRssReader.aspx.cs.
In this behind code we can achieve our goal to dynamically bind RssDataSource to Acccordion (note we
cannot do this in the client-side JavaScript mode since RssDataSource
is a server-side data source control). This is why we
find __doPostBack through which we can indirectly communicate
the client-side controls with the server-side controls (where we can succeed in
the dynamic binding).
OK, now we first create two dummy ASP.NET controls (you can
certainly find your own way): a Button and a TextBox control. Since they should
be "invisible" at run-time we set their sized to the smallest (1px X
1px) and accordingly set the background colors to LightGray (the background
color of the "buttonarea" panel).
Author's Note: You cannot directly
set the property Visible of the two dummy controls to "false"
or else you are sure to meet some run-time trouble. Just try it!
Next, by calling method "__doPostBack" above we
indirectly call the server-side click event handler, dummySrvBtn_Click(object
sender, EventArgs e), that is located inside the CodeFile AjaxRssReader.aspx.cs.
Here is the related source code for this function.
Listing 10
protected void dummySrvBtn_Click(object sender, EventArgs e)
{
RssDataSource1.Url = txtRssUrl2.Text.Trim();
Accordion1.DataSourceID = "RssDataSource1";
Accordion1.DataBind();
}
For now, we do not dwell on this code but leave this in the
next section.
By assigning the value of field Rss_URL to the attribute value (in relation to the server-side property Text) of the related HTML Input element
txtRssUrl2.ClientID (in corresponding to the ASP.NET server-side Id—txtRssUrl2), we can succeed in transfering
the data from the client side to the server side!
Finally, calling method "__doPostBack" will
certainly trigger a whole page refresh, which is quite contrary to the original
AJAX idea. This is why we have to introduce the ASP.NET AJAX server control
UpdatePanel which is used to enclose the Accordion control. Note that we use
the trigger AsyncPostBackTrigger to let the click event
of button '"ummySrvBtn" to trigger the UpdatePanel. Here is the
related HTML code.
Listing 11
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="dummySrvBtn" EventName="Click" />
</Triggers>
<ContentTemplate>
<ajaxToolkit:Accordion ID="Accordion1"
CssClass="myAccordion" HeaderCssClass="header"
……(omitted)
And by the way, we add an UpdateProgress control to gain a
better user experience.
Is the above an ugly solution? I sincerely expect zealous readers
to improve this and also welcome them to email
me.
Displaying the Content
As for displaying the clicked item-related RSS contents, it
is pretty easy for now. In fact, we have accomplished this task from the above listing.
By dynamically assigning a value to property Url of control
"RssDataSource1," binding it to control "Accordion1" and
invoking method DataBind of "Accordion1," we
can display the related RSS channel content that corresponds to the user
clicked channel.
Author's Notes: First, by looking
through the web I could not find the proper samples to dynamically assign data
to control RssDataSource. Second, I have commented out the field author from inside the <ContentTemplate> block of
control Accordion since there might exist RSS contents that do not contain this
field. Because I am a newbie to the Rss Toolkit and control Accordion, I cannot
find the more alternate solution for the programmer to dynamically control the displayable
field of the RSS channel within the control Accordion. For all these reasons I had
to make the test again and again and finally found the above ugly solution. So,
it is just for your reference.
Let us take a look at our final fruit, as illustrated in the
following figure.
Figure 5: The run-time snapshot of the sample after
the user has clicked item "Scott Guthrie"