Monday April 20, 2009

In Part Three of this series we continued to expand our sample Silverlight/SharePoint list application by adding an additional call to retrieve list detail. In this article we will use the results of our call for list detail to determine which columns should be displayed when we retrieve SharePoint list items. To simplify list item data retrieve we will also explorer a SharePointList helper class that is useful for building CAML queries and encapsulating list items results.

So far the calls we have made from our Silverlight application to the SharePoint lists web services have require only simple parameters. Our first call to GetListCollectionAsync required no parameters. Our call to GetListAsync required only the name of the list. Now we will up the anti and make calls to GetListItemsAsync.

GetListItemsAsync requires the caller to specify the name of the list, the view name, the fields to return, a CAML query, and other options.

The name of the list from which to retrieve list items. This can be either the list title or a GUID surrounded by curly braces e.g. “UserInfo” or “{D5098B8F-1C04-4dc7-AB86-65AD591A008B}”. Though the MSDN documents recommend using a GUID here instead of the actual list name, you should note that SharePoint list GUIDs are unique for each site implementation. If you are writing Silverlight components to be used on multiple SharePoint sites, the use of list names is a little more portable. If you insist on using a list GUID, you should retrieve the list GUID by first calling the GetList method.

string viewName

The GUID, surrounded by curly braces, of the view used to retrieve list items. Setting the viewName to string.empty or “” causes the default view for the specified list to be used.

This fields to be returned for each list item found. If null, all fields of the view will be returned. This xml fragment is of the form: <ViewFields> <FieldRef Name=”field1-name”/> <FieldRef Name=”field2-name”/> … <FieldRef Name=”fieldN-name”/> </ViewFields>

string rowLimit

A string representation of the maximum number of list items to be returned, or an empty string, if unspecified.

XElement queryOptions

A null if not specified, or an xml fragment containing a list of parameter setting based on the parameter of the SharePoint SPQuery object. SPQuery parameter documentation can be found here: SPQuery. For example: <QueryOptions> <ExpandUserField>True</ExpandUserField> </QueryOptions>

string webID

The GUID it of the SharePoint parent web site that contains the list, or a null if the site specified by the url of the web service should be used.

object userState

Any object that you wish to be passed to the asynchronous event handler that wil be called when this async method completes. userState be null.

Now that we know what method to use to enumerate list items from a SharePoint list, the next step is to modify the user interface of the application from Part Three of this series to allow us to select a list then view the list items. You will note that I have also added some additional radio buttons and check boxes toggle between list detail and list items or show the data as raw xml or in list format. I’ve added the “All” check box to toggle between passing a null value for the viewFields parameter (returns all fields) or a list of standard fields.

In order to support the new radio buttons and check boxes I extracted the call to the listsSoapClient and created a new updateListDetailPanel() function to make the call based on the option selected by the user. The orginally call to listsSoapClient is now in it's own method, called getListDetail. The code to make the new call to GetListItemsAsync is in the getListItems method. Note that when the "All" check box is checked a null is passed to the viewFields parameter which causes all fields specified in the view to be returned. When the "All" check box is unchecked a only a select subset of the standard SharePoint built-in fields are returned. The new code looks like this:

The next piece of code to write is the listsSoapClient_GetListItemsCompleted handler which is called when GetListItemsAysnc completes. Remember that all methods of the ListsSoapClient complete asynchronously. When the listsSoapClient is called, the Result property of the GetListItemsCompletedEventArgs will contain the root XElement node of the result set. An example of an xml tree returned by a call to GetListItemsAysnc can be seen here:

To set the itemsSource of our ListView control we will need to extract an enumeration of the <z:row> element from the returned xml document. To do this we will use the Descendants() method of the XElement node. The Descendents() method returns an enumeration of all matching child elements. It is important to note here though that the namespace prefix "z" is defined in the root element as the namespace "#rowset-schema" so you will need to specify both the name of the elmeent "row" and the namespace "#rowset-schema" using XName, it order for the call to Decendents() to return any matches.

I've cheated a little here by using the XAttributeConverter helper class that was introduced in Part Three. This helper class allows us to pass the XElement node enumeration directly to the ListView control as it's ItemsSource. Normaly Silverlight controls and data templates to not know how to bind to an XElement node nor how to extract XAttribute values. The XAttributeConverter helper class allows us to directly bind to attributes of an XMl node. To see how this is used take a look at the XAML code again, you should notice the data templates defined in the resources section of the XAML definition as follows:

If you wish to display other fields in the ListView, first look at the list with the "Raw" checkbox checked. Note that all user field names are prefixed by SharePoint with "ows_". Just add or remove bindings in the ListItemTemplate.

Compiling and running the code should produce something similar to the following images:

Note if you wish for the Silverlight control to take up the entire browser page just delete the Width and Height specified in the UserControl element of the XAML definition.