There are some very good
resources that provide code examples on how to bind an atlas listview control
to a datasource and dataservice (see below). There are also some interesting
posts on message boards describing problems with binding the Atlas listview
control to an xmldatasource. The current project that I am working on required
an implementation that uses client side binding to an xmldatasource, so I
thought that I would and blog about the journey.
The data service provides a
custom mechanism for using Microsoft specific technologies the dataset. There
are situations where architectural restrictions mean that as a developer we are
forced to connect to an existing web service. The mix 06 sample provides a good
training ground to play with atlas which this post is based on. You can
download it here.
The player page is the only page
that requests its data from a web service and an ideal way to practice how to
utilise xml with the Atlas listview control. The current page layout only shows
the current track playing in the play list. So I wanted to add some additional
functionality so that users can view all the items in their current play list.
First let’s start with the code
on the server to find out what is happening. On the server the main thing to
note is that the web service does require the WebOperation
attribute. Allowing the service to return xml or json here we are using xml.
On the client side of things add
the listview inside the script tags. Remember to wire up the propertyChanged
event handler with the update method declared in the Media Player class.
<listView
id="playListItems"
itemTemplateParentElementId="albumAddContainer"
incrementalRenderingSize="1" propertyChanged="update">
Then update
the descriptor.
td.addMethod("update");
Next add the bindings for the
listview.
<bindings>
<binding
property="data" dataContext="xmlPlayList"
dataPath="data" automatic="true" />
</bindings>
The
listview does support xml bindings but there is no explicit property and hence
the reason for using the data property instead. A little confusing as well
considering the declaration layout of the bindings for the media player control. Next add the
labels to the listview displaying the information of the tracks in the current
play list, allowing the user to view the list of tracks currently in the play
list. Finally we can get to the good stuff and do some plumbing,
use the xpath bindings to query the data and retrieve the xml data to populate
the UI controls label.
<label id="trackArtist">
<bindings>
<xpathBinding property="text" xpath="./artist/text()" />
</bindings>
</label>
Repeat the code above for the
other data that you want to customise the display with inserting the xpath
query to get the data you want.
The final step of
the script code is to update the xmldatasource and decorate it with a
propertyChanged event handler to update the data source when it changes. The
Atlas client script code needs to call the web service method explicitly using
the mn prefix.
<xmlDataSource
id="xmlPlayList"
autoLoad="true"
serviceURL="Services/PlayList.asmx?mn=GetTopAlbums"
xpath="/playList/item" propertyChanged="update">
<parameters count="0" />
</xmlDataSource>
Fire up the start
page in the sample and navigate to the player page. If everything has gone
smoothly then there will be a list of tracks in your current play list.
The propertyChanged
event is the key here, the listview control creation occurs before the web service
has responded with data so there is no data to present to the user and the
control is initially rendered with no results displayed. When the data arrives
at the client the update method is called and invokes a delegate in the atlas
framework called evaulateIn
. The listview then reloads displaying the updated data. The important part
to remember here is to fire the raise property changed event for a delegate to
update the properties that you want the control to display.
When binding a
client side Atlas control to a datasource using a dataservice there seems to be
no apparent timing issues, as I am assuming the datasource inherently makes the
call to the method binding.evaluateIn.
If you are
designing a site from scratch then utilising the dataservice and datasource
must be taken into consideration, however there will be payload and resulting
latency implications to take into consideration. For development teams wanting
to utilise Atlas technologies to catch the wave of web 2.0, extensibility, easy
to bake in UI technologies that can be developed to utilise standards compliant
web services is fundamental to the adoption of Atlas. Atlas client side UI
controls provide the developer with a way of achieving this goal.
Some useful Atlas
Links
Steve Marx http://smarx.com/
Wilco Bauwer http://www.wilcob.com/Wilco/Default.aspx
NiKHilk http://www.nikhilk.net/
Scott Guthrie http://weblogs.asp.net/scottgu/archive/tags/Atlas/default.aspx
DotNetSlackers http://www.dotnetslackers.com/Atlas/re-default.aspx
Quick Starts http://atlas.asp.net/docs/Atlas/default.aspx
Player.aspx
Nothing changes here….
<mix:mediaPlayer
id="mediaPlayer1"
playButton="playButton"
nextButton="nextButton" prevButton="prevButton">
<bindings>
<binding property="xmlData"
dataContext="xmlPlayList" dataPath="data" />
</bindings>
</mix:mediaPlayer>
Small change here add the
propertychanged event and provide a handler to update the data
<xmlDataSource
id="xmlPlayList"
autoLoad="true"
serviceURL="Services/PlayList.asmx?mn=GetTopAlbums"
xpath="/playList/item" propertyChanged="update">
<parameters count="0" />
</xmlDataSource>
<listView
id="playListItems"
itemTemplateParentElementId="albumAddContainer" incrementalRenderingSize="1"
propertyChanged="update">
<bindings>
<binding property="data" dataContext="xmlPlayList"
dataPath="data" automatic="true" />
</bindings>
<layoutTemplate>
<template layoutElement="albumAddContainer" />
</layoutTemplate>
<itemTemplate>
<template layoutElement="albumAddItem">
<label id="trackTitle">
<bindings>
<xpathBinding property="text" xpath="./title/text()" />
</bindings>
</label>
<label id="trackAlbum">
<bindings>
<xpathBinding property="text"
xpath="./albumTitle/text()" />
</bindings>
</label>
<label id="trackArtist">
<bindings>
<xpathBinding property="text" xpath="./artist/text()" />
</bindings>
</label>
</template>
</itemTemplate>
<emptyTemplate>
<template layoutElement="albumListLoadingMessage" />
</emptyTemplate>
</listView>