<UserControl xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" x:Class="SharePointListExample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SharePointListExample"
Width="525" Height="300">
<UserControl.Resources>
<local:XAttributeConverter x:Key="FromXAttribute"/>
<DataTemplate x:Key="ListDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=Title}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ListItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Title}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_ID}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Last_x0020_Modified}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Editor}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Created}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Author}"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition MaxHeight="30"/>
</Grid.RowDefinitions>
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0">
<ListBox x:Name="lbxListOfLists" ItemTemplate="{StaticResource ListDataTemplate}" SelectionChanged="lbxListOfLists_SelectionChanged" ></ListBox>
</ScrollViewer><basics:GridSplitter Grid.Column="1"></basics:GridSplitter>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5,5,5,5">
<RadioButton x:Name="rbListDetail" Content="List Detail" IsChecked="True" Checked="rbListDetail_Checked"/>
<RadioButton x:Name="rbListItems" Content="List Items" Margin="5,0,0,0" Checked="rbListItems_Checked"/>
<CheckBox x:Name="cbAll" Content="All" Margin="5,0,0,0" IsChecked="False" Click="cbAll_Click"/>
<CheckBox x:Name="cbRaw" Content="Raw" Margin="5,0,0,0" IsChecked="True" Click="cbRaw_Click"/>
</StackPanel>
<ScrollViewer x:Name="viewOutput" Grid.Row="1" HorizontalScrollBarVisibility="Visible">
<TextBox x:Name="txtOutput" IsReadOnly="True"></TextBox>
</ScrollViewer>
<ScrollViewer x:Name="viewListItems" Grid.Row="1" HorizontalScrollBarVisibility="Visible" Visibility="Collapsed">
<ListBox x:Name="lbxListItems" ItemTemplate="{StaticResource ListItemTemplate}" ></ListBox>
</ScrollViewer>
</Grid>
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5,5,5,5">
<TextBlock Margin="5,0,5,0" VerticalAlignment="Center">Sharepoint Url:</TextBlock>
<TextBox MinWidth="100" x:Name="txtSharePointUrl" Text="http://mysharepointserver.com/sites/mysite"></TextBox>
<Button x:Name="btnGo" Margin="5,0,0,0" Content="Go" Click="btnGo_Click"/>
</StackPanel>
</Grid>
</UserControl>
Next we need to modify the list selection changed event handler, from Part Three, to now call GetListItemsAsync when a list is selected. The original code looked like this:
private void lbxListOfLists_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (lbxListOfLists.SelectedItem is XElement)
{
XElement listItem = lbxListOfLists.SelectedItem as XElement;
string listName = listItem.Attribute("Title").Value;
ListsSoapClient listsSoapClient = createListsSoapClient();
listsSoapClient.GetListCompleted += new EventHandler<GetListCompletedEventArgs>(listsSoapClient_GetListCompleted);
listsSoapClient.GetListAsync(listName);
}
}
catch (Exception exception)
{
handleException("getList Failed", exception);
}
}
}
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:
/// <summary>
/// Get the list details by calling GetListAsync
/// </summary>
/// <param name="listName">The name of the list</param>
private void getListDetail(string listName)
{
ListsSoapClient listsSoapClient = createListsSoapClient();
listsSoapClient.GetListCompleted += new EventHandler<GetListCompletedEventArgs>(listsSoapClient_GetListCompleted);
listsSoapClient.GetListAsync(listName);
}
/// <summary>
/// Get the list items by calling GetListeItemsAsync
/// </summary>
/// <param name="listName">The name of the list</param>
private void getListItems(string listName)
{
ListsSoapClient listsSoapClient = createListsSoapClient();
listsSoapClient.GetListItemsCompleted += new EventHandler<GetListItemsCompletedEventArgs>(listsSoapClient_GetListItemsCompleted);
XElement query = new XElement("Query",
new XElement("OrderBy",
new XElement("FieldRef", new XAttribute("Name", "ID"))));
XElement viewFields;
if (cbAll.IsChecked.HasValue && cbAll.IsChecked.Value)
{
//get all fields
viewFields = null;
}
else
{
//get some of the standard fields
viewFields = new XElement("ViewFields",
new XElement("FieldRef", new XAttribute("Name", "Title")),
new XElement("FieldRef", new XAttribute("Name", "ID")),
new XElement("FieldRef", new XAttribute("Name", "Modified")),
new XElement("FieldRef", new XAttribute("Name", "Editor")),
new XElement("FieldRef", new XAttribute("Name", "Created")),
new XElement("FieldRef", new XAttribute("Name", "Author")));
}
listsSoapClient.GetListItemsAsync(listName, string.Empty, query, viewFields, string.Empty, null, null);
}
/// <summary>
/// Called to display the details for a selected list
/// </summary>
/// <param name="listData">The XElement code holding the currently selected list data</param>
private void updateListDetailPanel(XElement listData)
{
this.currentListData = listData;
string listName = listData.Attribute("Title").Value;
if (rbListDetail.IsChecked.HasValue && rbListDetail.IsChecked.Value)
{
getListDetail(listName);
}
else if (rbListItems.IsChecked.HasValue && rbListItems.IsChecked.Value)
{
getListItems(listName);
}
}
/// <summary>
/// Called when the user selects a specific list
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lbxListOfLists_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
if (lbxListOfLists.SelectedItem is XElement)
{
XElement listItem = lbxListOfLists.SelectedItem as XElement;
updateListDetailPanel(listItem);
}
}
catch (Exception exception)
{
handleException("getList Failed", exception);
}
}
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:
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="3">
<z:row ows_Attachments="0" ows_LinkTitle="A" ows_Alpha="A" ows_Gamma="Choice 1" ... />
<z:row ows_Attachments="0" ows_LinkTitle="B" ows_Alpha="B" ows_Gamma="Choice 2" ... /><
z:row ows_Attachments="0" ows_LinkTitle="C" ows_Alpha="C" ows_Gamma="Choice 3" ... /></
rs:data>
</listitems>
|
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.
/// <summary>
/// Called when GetListItemsAysnc completes
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void listsSoapClient_GetListItemsCompleted(object sender, GetListItemsCompletedEventArgs e)
{
try
{
txtOutput.Text = e.Result.ToString();
this.lbxListItems.ItemsSource = e.Result.Descendants(XName.Get("row", SHAREPOINT_ROWSET_NAMESPACE));
}
catch (Exception exception)
{
handleException("GetListItems Failed", exception);
}
}
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:
|
<UserControl.Resources>
<local:XAttributeConverter x:Key="FromXAttribute"/>
<DataTemplate x:Key="ListDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=Title}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ListItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Title}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_ID}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Last_x0020_Modified}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Editor}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Created}"/>
<TextBlock Margin="5" Text="{Binding Converter={StaticResource FromXAttribute}, ConverterParameter=ows_Author}"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
|
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.