binding a dynamic pivot in windows phone 7

I’m currently working on a Windows Phone 7 application that needs a dynamic Pivot. For every item in a list there should be a pivot item. Besides that, every dynamic pivot item should have a listbox that is bound to another list. I found very little information on these topics so I decided to write it down myself.

Both the header binding and the listbox binding are done from the same class. The class is called DemoClass and contains a string Name that will be bound to the header of the pivot item and a list of strings called Result that will be bound to the pivot item’s body. Here’s the code for the class:

Code Snippet
  1. using System.Collections.ObjectModel;
  2.  
  3. namespace BindingDynamicPivotDemo
  4. {
  5.     public class DemoClass
  6.     {
  7.         public string Name { get; set; }
  8.         public ObservableCollection<string> Result { get; set; }
  9.  
  10.         public DemoClass()
  11.         {
  12.             Result = new ObservableCollection<string>();
  13.         }
  14.     }
  15. }

I used ObservableCollection here instead of List because ObservableCollection already implements INotifyPropertyChanged and takes care of notifying all it’s subscribers when it changes. It’s perfectly possible to use a IList<string> instead of the ObservableCollection but then the DemoClass needs to implement INotifyPropertyChanged. In the constructor of the class the collection gets initialized.

Next thing I needed was a viewmodel to bind to my xaml page. The viewmodel declares a collection of DemoClass instances and fills those instances with dummy data.

Code Snippet
  1. using System;
  2. using System.Collections.ObjectModel;
  3.  
  4. namespace BindingDynamicPivotDemo
  5. {
  6.     public class MainViewModel
  7.     {
  8.         public ObservableCollection<DemoClass> PivotItems { get; set; }
  9.         
  10.         public MainViewModel()
  11.         {
  12.             PivotItems = new ObservableCollection<DemoClass>();
  13.  
  14.             //load pivot headers
  15.             LoadData();
  16.  
  17.             //load random dummy data for the pivot body
  18.             FillLists();
  19.         }
  20.  
  21.         public void LoadData()
  22.         {
  23.             //pivot headers
  24.             for (int i = 1; i <= 10; i++)
  25.             {
  26.                 DemoClass newClass = new DemoClass {Name = "pivotItem " + i};
  27.  
  28.                 PivotItems.Add(newClass);
  29.             }
  30.         }
  31.  
  32.         public void FillLists()
  33.         {
  34.             Random rnd = new Random();
  35.  
  36.             //fill each list with dummy data, this will be shown in the pivot body
  37.             foreach (DemoClass pivotItem in PivotItems)
  38.             {
  39.                 pivotItem.Result.Clear();
  40.  
  41.                 for (int j = 0; j < 10; j++)
  42.                 {
  43.                     pivotItem.Result.Add("item " + rnd.Next(0, 1000));
  44.                 }
  45.             }
  46.         }
  47.     }
  48. }

I am again using an ObservableCollection for the same reason as I did in the DemoClass. LoadData() creates 10 instances of DemoClass and adds them to the PivotItems collection. FillLists() will fill the Result collection of every DemoClass instance with random dummy data.

Next step is to let the view know where it needs to look for its data. This can be done from xaml or from code behind. MVVM Light takes the xaml approach while the default Visual Studio projects do it from code behind, since this is a default project I followed the code behind approach. This is how my MainPage.xaml.cs looks liks.

Code Snippet
  1. using System.Windows;
  2. using Microsoft.Phone.Controls;
  3.  
  4. namespace BindingDynamicPivotDemo
  5. {
  6.     public partial class MainPage : PhoneApplicationPage
  7.     {
  8.         // Constructor
  9.         public MainPage()
  10.         {
  11.             InitializeComponent();
  12.  
  13.             // Set the data context of the listbox control to the sample data
  14.             DataContext = App.ViewModel;
  15.         }
  16.  
  17.         private void Button_Click(object sender, RoutedEventArgs e)
  18.         {
  19.             App.ViewModel.FillLists();
  20.         }
  21.     }
  22. }

Instantiation of the ViewModel occurs in App.xaml.cs and is auto-generated code. The Button_Click method is an event handler for a button, obviously. It will call a method on the ViewModel that regenerates new random dummy data for the pivot body. This shows how an ObservableCollection gives a powerful auto-updating binding while keeping the DemoClass nice and clean.

Now let’s take a look at the xaml and specifically at the bindings. This is the MainPage.xaml.

Code Snippet
  1. <Grid x:Name="LayoutRoot" Background="Transparent">
  2.         <!--Pivot Control-->
  3.         <controls:Pivot x:Name="PivotPlatform" Margin="0,0,8,77" Title="BindingDynamicPivotDemo" ItemsSource="{Binding PivotItems}" >
  4.             <controls:Pivot.HeaderTemplate>
  5.                 <DataTemplate>
  6.                     <TextBlock Text="{Binding Name}"/>
  7.                 </DataTemplate>
  8.             </controls:Pivot.HeaderTemplate>
  9.             <controls:Pivot.ItemTemplate>
  10.                 <DataTemplate>
  11.                     <ListBox ItemsSource="{Binding Result}">
  12.                         <ListBox.ItemTemplate>
  13.                             <DataTemplate>
  14.                                 <TextBlock TextWrapping="Wrap" Text="{Binding}" />
  15.                             </DataTemplate>
  16.                         </ListBox.ItemTemplate>
  17.                     </ListBox>
  18.                 </DataTemplate>
  19.             </controls:Pivot.ItemTemplate>
  20.         </controls:Pivot>
  21.         <Button Content="Randomize" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,0,4" Click="Button_Click"/>
  22.     </Grid>

I only pasted the layoutRoot grid here because all the xml namespaces are the default ones from a WP7 project. So for starters I’ve bound the Pivot’s ItemsSource to the PivotItems collection. Then I declare two templates, the header template is the title of the pivot item, by binding it to name it will use the Name property from the DemoClass. Since the Pivot’s ItemsSource is bound to PivotItems, the textblock in the header template is now bound to PivotItems.Name. The itemtemplate is what makes up the pivot’s body, it contains a listbox that is bound to PivotItems.Result. Underneath the pivot is a button that triggers the event handler in MainPage.xaml.cs.

When this is executed you’ll see an automatically generated pivot bound to dummy data, every time the button is clicked new data will be generated and shown in the pivot immediately thanks to the ObservableCollection.

screen

The source of this project can be found here.

Conclusion

In this small article I explained how you can databind a pivot so that it’s items are automatically generated and bound to other properties. It’s not hard to do but it took me some time to figure out so I hope I’ve helped someone by writing down my findings.

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment