2011/04/04

I’ve spent the weekend trying to work out how to create the pages you see on a Pivot Page dynamically through code. It took a lot of web searching and trial and errors but I seem to have managed to get the basics of this worked out. I’m posting this to help other people who are trying to do the same thing. In this case it works, but if anyone else has a better/more efficient way of doing this I would be interested in looking at it.

The database/Web server has a directory full of images which the web service will pass back to the client using XML. Each image can belong to a image type. Each of these types will be a Pivot Item in the Pivot page. The list of images for each of these types will be displayed on each of these Pivot items.

I started by creating a pivot page and deleted any pivot items that where in the XAML. I then created the following Page Load event code:

This will call the GetImageTypes web service on the server (I will document these in another post)
Once the request has been completed, all the image types will be sent back to the client in XML format.

' Routine to handle the Get Image Types completed event.
Private Sub client_GetImageTypesCompleted(ByVal sender As Object, ByVal e As adminServiceReference.GetImageTypesCompletedEventArgs)
If e.Error Is Nothing Then
Dim types = e.Result
' did the server side report an error?
If types.ErrorMessage = "" Then
' no so loop through each Image type in the xml result
For Each ele In types.xml...<type>
' We need to create a new Pivot item for each image type
Dim p As New PivotItem
' set the header name to the lowercase version of the type name
' this is to fit in with the standard way of showing pivot items
p.Header = ele.Value.ToLower
' add the pivot item to the pivot page
imagePivotControl.Items.Add(p)
' now request all the images under of that type
Dim str As New StrType
str.text = ele.Value
_client.GetImagesAsync(str)
Next
Else
' The server side got an error so display the error
' to aid in debugging.
MessageBox.Show(types.ErrorMessage)
End If
Else
' the request to the webservice caused an error so
' display this error to try and help debug the problem.
MessageBox.Show(e.Error.Message)
End If
End Sub

The comments in the above code should lead you through the creation and titling of the PivotItem and used XML Literals a very handy feature in VB to make code more readable when interacting with XML. (This should be implemented in C#)

For each image type pivot item created it will also request all the images for that image type which the following code will handle.

' a routine to handle the Get Images completed event.
Private Sub client_GetImagesCompleted(ByVal sender As Object, ByVal e As adminServiceReference.GetImagesCompletedEventArgs)
' Did the request cause an error
If e.Error Is Nothing Then
Dim imgs = e.Result
' Did the web server get an error while processing the request.
If imgs.ErrorMessage = "" Then
' no error so start searching the PivotItems to find the one matching
' the type that we requested the images for.
For Each pg As PivotItem In imagePivotControl.Items
If pg.Header.ToString = imgs.type.ToLower Then
' We have a match so create a listbox item to hold the details
Dim lb As New ListBox
' we need a counter to display next to the image
' this is only temorary until we have an image there
Dim cnt As Integer = 0
' Loop through all the image elements in the returned XML
For Each ele In imgs.xml...<image>
' We need to create a grid to store the information in the
' list box item this is the equivilent to the following XAML
'
' <grid>
' <Grid.RowDefinitions>
' <RowDefinition Height="Auto"/>
' </Grid.RowDefinitions>
' <Grid.ColDefinitions>
' <ColDefinition Width="100"/>
' <ColDefinition Width="Auto"/>
' </Grid.RowDefinitions>
' </grid>
' Create the grid object
Dim grd As New Grid
' Create the row definition objec
Dim rowdef As New RowDefinition
' the row definition object uses a object called gridlength
' we create one of these and set it to Auto
Dim glen As New GridLength
glen = GridLength.Auto
' we add the height information to the row definition
rowdef.Height = glen
' now we add the row definition to the list of row definitions
' in the grid object
grd.RowDefinitions.Add(rowdef)
' Now we need to create a column definition
Dim coldef As New ColumnDefinition
' the first column has a width of 100 pixels for now, it will
' contain an image eventually and we can leave it set to auto.
coldef.Width = New GridLength(100)
' add the column definition to the list of column definitions in
' the grid object.
grd.ColumnDefinitions.Add(coldef)
' we now create the second column definition to auto which is the
' same as we used with the row definiton so lets just re-use
' this object.
coldef = New ColumnDefinition
coldef.Width = glen
' add the final column definition to the collection of column
' definitions in the grid object.
grd.ColumnDefinitions.Add(coldef)
' Now we start to add the data, first we create a textblock that
' will be used to hold the count.
' This is the equivilent to the following XAML.
'
' <TextBox Grid.Column="0" Grid.Row="0" Text="{cnt.string}"/>
'
Dim tb = New TextBlock
' we set the row and column of the textblock to make it appear in
' the correct loctation
Grid.SetColumn(tb, 0)
Grid.SetRow(tb, 0)
' set the text property of the text block to the current count
tb.Text = cnt.ToString
' add the textblock to the children objects of the grid.
grd.Children.Add(tb)
' Now we add a new text block which will display the name of the
' image file on the server.
' This is the equivilent to the following XAML
'
' <TextBox Grid.Column="1" Grid.Row="0" Text="{ele.value}"/>
'
tb = New TextBlock
' set the row and column information of the text block.
Grid.SetColumn(tb, 1)
Grid.SetRow(tb, 0)
' pull the content of the image item ( <image>value</image> ) and
' put this into the text property of the text block
tb.Text = ele.Value
' add the text block to the child objects of the grid.
grd.Children.Add(tb)
' Now we create the list box item to add to the list box in
' the pivot item.
Dim lbi As New ListBoxItem
' add the grid to the listbox item
lbi.Content = grd
' and add the list box item to the list box
lb.Items.Add(lbi)
' increment the counter
cnt += 1
Next
' add the list box to the pivot item.
pg.Content = lb
End If
Next
Else
' the server produced and error so display to aid in debugging
MessageBox.Show(imgs.ErrorMessage)
End If
Else
' the request caused and error so display this to aid in debugging
MessageBox.Show(e.Error.Message)
End If
End Sub

Again I have commented the code to lead you through how the listbox and listbox items are created from the XML results and used to populate the pivot item for each image type.