Nico's digital footprint

I grew up in the nineties, that makes me awesome by default

A practical guide to MVVM (Light)–Part 2

by Nico

A practical guide to MVVM (Light) – Part 1

In part 1 I’ve shown you how to setup a new Windows Phone project with MVVM Light, how to hookup everything and we’ve seen what databinding is and how it works. In this part we’re going to build on that same project, delving a bit deeper into MVVM in a practical way.

Intro

In part 2 we’ll have a look at how to navigate from a list page, like the one we’ve created in part 1, to a detail page. We’ll need to inform the viewmodel on what item was clicked so that it can fetch more detailed information from the datastore. We’ll also have a look at value converters, a feature not really MVVM related but one that’s really important so I’m including it here anyway.

Navigation

There are a few ways to get navigation done in a Windows Phone app. You can use a NavigationService class for example. A class that can get injected via SimpleIoc and that has a .Navigate function, the Cimbalino Toolkit has one build-in for example. One other way to do navigation without delving into code-behind code in the view is by using Behaviors and Actions in XAML. Don’t worry, you don’t need to remember the exact syntax as long as you have Blend.

Open up the MainPage.xaml of our Part 1 project in Blend and have a look at the Assets Tab. (Quick tip: if you want to open a certain page in Blend, right-click it in Visual Studio and select “Open in Blend”, this also works for opening a page from Blend in Visual Studio).

In the Behaviors section you’ll find a bunch of Actions and Behaviors. An interesting one here is the NavigateToPageAction, drag and drop that one onto the ListBox. You’ll notice that the Action has attached itself to the ListBox if you have a look at the Objects & Timeline pane.

Before we can navigate we need to create a new page, add a page called DetailPage.xaml to the View folder of the project. Creating the page can be done from either Blend or Visual Studio. After creating the DetailPage, go back to MainPage in Blend and select the NavigateToPageAction that’s attached to the Listbox in the Objects & Timeline pane. Go to the properties.

You’ll see here that the action contains a trigger. There we can select what event from the Listbox will trigger the action, set this to SelectionChanged. In the dropdown for TargetPage you should see MainPage and DetailPage (and any other pages you might have created), set it to DetailPage and run the app. Click on an item and you’ll see that the app navigates to the detailpage. This is what the action looks like in XAML.

Code Snippet
  1. <ListBox ItemTemplate="{StaticResource PersonTemplate}" ItemsSource="{Binding Persons}">
  2.     <i:Interaction.Triggers>
  3.         <i:EventTrigger EventName="SelectionChanged">
  4.             <ec:NavigateToPageAction TargetPage="/View/DetailPage.xaml" />
  5.         </i:EventTrigger>
  6.     </i:Interaction.Triggers>
  7. </ListBox>

Loading detailed data for clicked item

When we select an item we navigate to a detail page. It would be nice to effectively show all the details. When using a ListBox this is pretty easy. We can just define a property on the viewmodel and bind the ListBox’s SelectedItem property to the property on the viewmodel. The property could look something like this

Code Snippet
  1. public Person SelectedPerson
  2. {
  3.     get { return _selectedPerson; }
  4.     set
  5.     {
  6.         if (_selectedPerson == value) return;
  7.         _selectedPerson = value;
  8.         RaisePropertyChanged(() => SelectedPerson);
  9.         LoadDetails();
  10.     }
  11. }

The binding on the ListBox would look like this

Code Snippet
  1. <ListBox ItemTemplate="{StaticResource PersonTemplate}
  2.          ItemsSource="{Binding Persons}"
  3.          SelectedItem="{Binding SelectedPerson,
  4.                                 Mode=TwoWay}">

Notice that we have to specify that this is a two-way binding. If we don’t, the property will not get updated from the view. Databinding by default is OneWay, from the viewmodel to the view.

While this is a valid way of working, it has some issues.

  • LongListSelector doesn’t support binding to SelectedItem (I described workarounds for this here and here)
  • The DetailPage needs to have MainViewModel as datacontext, which is possible and allowed but often this means that a viewmodel turns into a superclass that handles the datacontext for every view.

On to the next possibility we go!

EventToCommand

The way of passing the selecteditem from the view to the viewmodel and to the next viewmodel I’m about to describe takes a bit more setup than the previous part. However, while it is a bit more work, it’s my preferred way of working. To me this feels like the “MVVM way” but use whatever feels most comfortable for you.

Go into Blend and delete the NavigateToPageAction that is still attached to the ListBox. Go back to the Assets pane, to the list of Behaviors. You’ll find that in the list is an EventToCommand behavior. This allows us to hook up events fired by controls in the view to trigger certain actions on the viewmodel. Drag & drop the EventToCommand onto the ListBox.

Before specifying the target command for the behavior, we’ll have to add one to the viewmodel first. Windows Phone has an interface called ICommand that we can use for binding. MVVM Light comes with two implementations of ICommand called RelayCommand and RelayCommand<T>. We’re going to use the generic version RelayCommand<T> because this way we can get the event arguments into our viewmodel.

Code Snippet
  1. private RelayCommand<SelectionChangedEventArgs> _selectionChangedCommand;
  2.  
  3. public RelayCommand<SelectionChangedEventArgs> SelectionChangedCommand
  4. {
  5.     get
  6.     {
  7.         return _selectionChangedCommand ??
  8.                (_selectionChangedCommand = new RelayCommand<SelectionChangedEventArgs>(OnSelectionChanged));
  9.     }
  10. }

When using the generic version of RelayCommand we specify the type of T as the type of eventargs we’re expecting. Note that this can also be a string that’s passed in as commandparameter for example when binding to a button’s command property.

SIDENOTE – the ?? operator: If you’ve never seen the ?? operator before, it checks if whatever’s on its leftside is not null, if it is it executes whatever’s on its rightside. In this case the rightside will only get executed the very first time the command is called, that’s when the private field is instantiated.

the parameter passed into the RelayCommand<T> constructor is the action that we’ll be executing when the command is called.

Code Snippet
  1. private void OnSelectionChanged(SelectionChangedEventArgs args)
  2. {
  3.     throw new System.NotImplementedException();
  4. }

We’ll complete this in a minute, just leave it like this to make the application compile.

Bind the EventToCommand Command property to the RelayCommand either through Blend or in XAML. Make sure to check the PassEventArgsToCommand checkbox when going via Blend. This is what the XAML should look like.

Code Snippet
  1. <ListBox ItemTemplate="{StaticResource PersonTemplate}"
  2.     ItemsSource="{Binding Persons}">
  3.     <i:Interaction.Triggers>
  4.         <i:EventTrigger EventName="SelectionChanged">
  5.             <Command:EventToCommand PassEventArgsToCommand="True" Command="{Binding SelectionChangedCommand, Mode=OneWay}"/>
  6.         </i:EventTrigger>
  7.     </i:Interaction.Triggers>
  8. </ListBox>

No more SelectedItem binding. If we place a breakpoint in the OnSelectionChanged method and check the parameter you should see the selected item in there.

So far, we’re using the controls their events, using a behavior to pass the eventhandler to a command on our ViewModel. No code behind required, clean MVVM setup. The next step is to navigate to another page and pass the selected item to another viewmodel. Let’s start by navigating.

Navigating via the ViewModel

I’ve mentioned before that navigating from within the viewmodel can be done by using a NavigationService. It’s time to do just that. A NavigationService is not included in Windows Phone so we’ll either need to write one or use an existing one. I’m going to do the latter and use an existing one.

Use either NuGet or the Package manager console to add the Cimbalino Windows Phone toolkit to the project

Install-Package Cimbalino.Phone.Toolkit

Now it’s time to revisit the ViewModelLocator. Remember SimpleIoc? We used the ViewModelLocator to register services and use constructor injection to inject those services into our viewmodels. First add a using statement to the ViewModelLocator

Code Snippet
  1. using Cimbalino.Phone.Toolkit.Services;

Next, register the NavigationService in SimpleIoc. (line 14)

Code Snippet
  1. public ViewModelLocator()
  2. {
  3.     ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
  4.  
  5.     if (ViewModelBase.IsInDesignModeStatic)
  6.     {
  7.         // Create design time view services and models
  8.         SimpleIoc.Default.Register<IDataService, DesignDataService>();
  9.     }
  10.     else
  11.     {
  12.         // Create run time view services and models
  13.         SimpleIoc.Default.Register<IDataService, DataService>();
  14.         SimpleIoc.Default.Register<INavigationService, NavigationService>();
  15.     }
  16.  
  17.     SimpleIoc.Default.Register<MainViewModel>();
  18. }

Back to the MainViewModel, we add a new parameter to its constructor.

Code Snippet
  1. private INavigationService _navigationService;
  2. public MainViewModel(IDataService dataService, INavigationService navigationService)
  3. {
  4.      _navigationService = navigationService;

Using the NavigationService is pretty easy.

Code Snippet
  1. private void OnSelectionChanged(SelectionChangedEventArgs args)
  2. {
  3.     _navigationService.NavigateTo("/View/DetailPage.xaml");
  4. }

Do be careful with the path to the page, it’s a string so no intellisense. If the page is in a folder make sure to start with “/”. Run the app, click an item. The app should navigate to the DetailPage, just like we had before. Time to add the PersonViewModel. Add a class named PersonViewModel and make it inherit ViewModelBase, that’s enough for now.

Every new viewmodel in an MVVM Light application needs to be added to the ViewModelLocator. We need to register the viewmodel in SimpleIoc and create a property to allow databinding. First register the viewmodel in the ViewModelLocator’s constructor

Code Snippet
  1. SimpleIoc.Default.Register<PersonViewModel>();

Next is the property

Code Snippet
  1. public PersonViewModel Person
  2. {
  3.     get
  4.     {
  5.         return ServiceLocator.Current.GetInstance<PersonViewModel>();
  6.     }
  7. }

Now we can set the DetailPage’s datacontext to the PersonViewModel by adding this to the opening tag of the page.

Code Snippet
  1. DataContext="{Binding Person,
  2.                       Source={StaticResource Locator}}"

For your reference, here’s the complete tag

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="MvvmDemo.View.DetailPage"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  7. xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  8. DataContext="{Binding Person,
  9.                       Source={StaticResource Locator}}"
  10. FontFamily="{StaticResource PhoneFontFamilyNormal}"
  11. FontSize="{StaticResource PhoneFontSizeNormal}"
  12. Foreground="{StaticResource PhoneForegroundBrush}"
  13. Orientation="Portrait"
  14. SupportedOrientations="Portrait"
  15. shell:SystemTray.IsVisible="True"
  16. mc:Ignorable="d">

Messaging

Now that we have two viewmodels, we need to setup a form of communication between them. Luckily for us, MVVM Light has something in place for this called the Messenger. The Messenger is a class that receives and delivers messages. One viewmodel subscribes for a certain message, the other viewmodel sends a message and the messenger makes sure it gets delivered nicely. The messenger can take any type and send it as a message, we could for example send an entire person, or the ID of a person and send it as an integer. But in a bigger app this could get complicated, imagine if 5 viewmodels start listening for integers but one is expecting the id of a product, another one expects the id of a person while a third one expects a result of some sorts. It would be a lot of work to get the subscribe / unsubscribe just right. That’s why I advice you to make it a habit to encapsulate the data in a special message class. Like for example to send our selected person over to the PersonViewModel.

Code Snippet
  1. public class PersonSelectedMessage : MessageBase
  2. {
  3.     public Person SelectedPerson { get; set; }
  4.     public PersonSelectedMessage(Person selectedPerson)
  5.     {
  6.         SelectedPerson = selectedPerson;
  7.     }
  8. }

As you can see, this is a really simple class with only one purpose: encapsulate a Person instance. The MessageBase baseclass is an MVVM Light class that contains some info about the sender and the target but I use this mainly to make the classes easier to recognize as MVVM Light messages. I also place all those message classes in a Messages folder in my project.

Let’s subscribe to this type of message from the PersonViewModel. First add a Person property to the PersonViewModel that we can bind to.

Code Snippet
  1. private Person _selectedPerson;
  2.  
  3. public Person SelectedPerson
  4. {
  5.     get { return _selectedPerson; }
  6.     set
  7.     {
  8.         if (_selectedPerson == value) return;
  9.  
  10.         _selectedPerson = value;
  11.         RaisePropertyChanged(() => SelectedPerson);
  12.     }
  13. }

Then add this in the PersonViewModel constructor.

Code Snippet
  1. public PersonViewModel()
  2. {
  3.     Messenger.Default.Register<PersonSelectedMessage>(this, msg =>
  4.     {
  5.         SelectedPerson = msg.SelectedPerson;
  6.     });
  7. }

This registers our current instance of PersonViewModel to receive messages of the PersonSelectedMessage type. We will send this message from the MainViewModel in the OnSelectionChanged method that fires when selecting a person in the ListBox.

Code Snippet
  1. private void OnSelectionChanged(SelectionChangedEventArgs args)
  2. {
  3.     _navigationService.NavigateTo("/View/DetailPage.xaml");
  4.     Messenger.Default.Send(new PersonSelectedMessage(args.AddedItems[0] as Person));
  5. }

If you set a breakpoint in the action that fires when a message arrives and try to select a person the first time it will probably fail. This is because the message departs before the PersonViewModel has had a chance to initialize and register for the message, it will be sent but it will never arrive. If you hit the back key back to the MainPage and select another person it will arrive because the PersonViewModel instance already exists and is listening to the message. The quickest (and easiest) way to fix this is to make sure that PersonViewModel is initialized when the app launches. We can use an overload of SimpleIoc’s register method for this.

In the ViewModelLocator, add true as a parameter to the registration

Code Snippet
  1. SimpleIoc.Default.Register<PersonViewModel>(true);

This will initialize the class at the moment of registration and it will register itself as a subscriber for the PersonSelectedMessage. After binding the page title to SelectedPerson.Name and running the app this is the result:

If this was a real application you would use the action of the messenger to fetch the detailed information of the selected item. DataBinding takes care of displaying the data on screen.

Conclusion

In this second part of my practical guide to MVVM Light I’ve discusses the way I usually work to select an item from a list, navigate to a detail page and fetch / show detailed information.

Some more MVVM related articles:

Some more in depth IOC/DI articles:

Feel free to ping me on Twitter (@NicoVermeir) should you have any questions.

The code for this second part can be found on OneDrive.


Tags:

.Net | Binding | MVVM Light | Metro | Silverlight | WP7 | WP8 | WPF | WinRT | Windows 8 | XAML

Branching XAML Styler

by Nico

Some time ago I blogged about having recompiled the great XAML Styler plugin so it would install into Visual Studio 2013. The recompiled plugin suddenly became an unexpected success and it got me thinking that this plugin should really continue to exist, even if the original author isn’t supporting it anymore (not sure of this but it has been quite some time since he pushed anything to Codeplex).

After waiting around a bit I’ve decided to download the original source code, get it up and running in Visual Studio 2013 and push it to both Github and the Visual Studio gallery. So I’m happy to announce that the code can be found at Github and the VS2013 version of the plugin can be found at the Visual Studio Gallery

The future?

The version that is now on the gallery is the exact same version that I’ve compiled back in November. It’s the plugin that the original author created but recompiled with the VS2013 SDK. I did create a new VS Package project to be able to have it on the gallery side by side with the original plugin.

As for the future of the project, I’m currently going through the source code, getting to know the application and the code that makes it tick. Afterwards I’m planning on having a look at the logged issues on the original Codeplex site and tackle those.

Issues

Should you run into any issues while using the forked plugin please log an issue on the Github page.

Contributions

So you want to contribute? Great! Fork the Github version and go wild! Create a Pull request when you’re ready and if everything checks out I’ll happily merge your changes into the main branch and give props to every contribution you make.

Let’s keep this plugin alive and make it even better together!


Tags:

.Net | Community | Patterns | Silverlight | WP7 | WP8 | WPF | WinRT | Windows 8 | XAML | github | OSS

Filtering collections from XAML using CollectionViewSource

by Nico

I find that I often run into the need of separating a collection of items into several collections just so I can bind them to multiple listboxes, for example a list of sessions spanning several tracks and each track is shown in his own listbox in a pivotitem. To get this done you can start by adding multiple collections to your viewmodel and divide the items there. However this makes your viewmodel very big in a very short time. A better way to do this is using CollectionViewSource items in XAML. Let me show you how.

First thing I did was building a demo class existing out of a title and a description, these two properties will be shown in the listbox later on. A third property is the one we’ll use to filter the data, here’s the completed class.

public class DemoClass
{
    public string Title { get; set; }
    public string Description { get; set; }
    public Pivot PivotToAppearIn { get; set; }
}

Nothing special here. Notice the Pivot instance, this is just an Enum that will be the way to filter later on.

public enum Pivot
{
    First,
    Second,
    All
}

For the demo’s purpose I’ll be creating a bunch of dummy data in the viewmodel. The project template I’ve used here is the default pivot app template in the Windows Phone 7.1.1 SDK. It comes with a bunch of dummy data, I’ve used the same data but put them in instances of the DemoClass. Those instances are put inside an ObservableCollection.

This is the viewmodel

public class MainViewModel : INotifyPropertyChanged
{
    public const string ItemsPropertyName = "Items";
    private ObservableCollection<DemoClass> items;
    public ObservableCollection<DemoClass> Items
    {
        get
        {
            return items;
        }

        set
        {
            if (items == value)
            {
                return;
            }

            items = value;
            NotifyPropertyChanged(ItemsPropertyName);
        }
    }

    public MainViewModel()
    {
        this.Items = new ObservableCollection<DemoClass>();
        LoadData();
    }

    public void LoadData()
    {
        Items.Add(new DemoClass 
        { 
            Title = "runtime one", 
            Description = "Maecenas praesent accumsan bibendum", 
            PivotToAppearIn = Pivot.First 
        });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (null != handler)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

So we’ve got our basic bindable property here and a method that loads in the dummy data. In the demo project there’s obviously more then one item in the collection, there’s about 16 to be precise.

In the design I didn’t change a lot from the default template. I’ve just copied the ItemTemplate from the listbox to the pageresources so that it can be reused in the second listbox.

This is the template.

<phone:PhoneApplicationPage.Resources>
    <!-- template for the listboxes -->
    <DataTemplate x:Name="ListBoxTemplate">
            <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                <TextBlock Text="{Binding Title}" TextWrapping="Wrap" 
                           Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                <TextBlock Text="{Binding Description}" TextWrapping="Wrap" 
                           Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
            </StackPanel>
        </DataTemplate>
</phone:PhoneApplicationPage.Resources>

All right now that the preparations are set, time to get into the filtering. First step is to add a CollectionViewSource for each listbox. These are set on the same place as I’ve put the listbox ItemTemplate, in the pageresources. For this demo I need two CollectionViewSources.

<CollectionViewSource x:Name="FirstPivot" Filter="FirstPivot_Filter" Source="{Binding Items}" />
<CollectionViewSource x:Name="SecondPivot" Filter="SecondPivot_Filter" Source="{Binding Items}" />

So what’s all this? x:Name is like in any other XAML object, it’s just the name that can be used to reference the object. The source is the ObservableCollection that was created in the viewmodel. And last but definitely not least is the Filter event. This event will fire for every item in the collection that is bound to the Source property.

Now for the event handler, I’ll just post the event handler FirstPivot_Filter here because they are basically the same.

private void FirstPivot_Filter(object sender, System.Windows.Data.FilterEventArgs e)
{
    e.Accepted = (e.Item as DemoClass).PivotToAppearIn == Model.Pivot.First || 
        (e.Item as DemoClass).PivotToAppearIn == Model.Pivot.All;
}

FilterEventArgs has two properties, Accepted is a boolean that when true shows the item in the listbox that is bound to the CollectionViewSource. Item is the current item in the collection. Remember that this event is triggered for each item in the collection. So what we do here is casting the Item property to an instance of DemoClass then check if the PivotToAppearIn property, that was an instance of the enum, is either First or All.

Now that we have the CollectionViewSources and the event handlers in place it’s time to bind the ViewSource to the listbox.

<controls:PivotItem Header="first">
    <ListBox x:Name="FirstListBox" Margin="0,0,-12,0" 
             ItemsSource="{Binding Source={StaticResource FirstPivot}}"
             ItemTemplate="{StaticResource ListBoxTemplate}" />
</controls:PivotItem>

The bindingsource of ItemsSource is bound to the CollectionViewSource that filters for this listbox. And that’s it!

 

In this article I’ve shown how you can filter a collection using a CollectionViewSource in XAML. This is an easy and fast way to visually filter data while keeping a clean ViewModel.

Download the Demo project here.


Tags:

.Net | Binding | MVVM Light | Windows 8 | XAML | WP7 | WP8 | Silverlight | Metro | Devices

Binding a dynamic Pivot in Windows Phone 7

by Nico

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.


Tags:

.Net | WP7 | XAML | Binding | Silverlight

Techdays Belgium 2011

by Nico

The Belgian Microsoft Techdays 2011 will take place 26-27-28 April at Metropolis Antwerp.

I'll be attending, hope it will be as good as last year.
Things I look forward to:

  • Silverlight 5
  • C# 5 (asynchrony in particular)
  • HTML5 and CSS3
  • Windows Phone 7 development
  • Hopefully some XNA session

Info on the techdays can be found here


Tags:

.Net | Web development | HTML | Silverlight | Windows programming

  Log in

About the author

Hi,

My name is Nico, I’m an MVP Windows Platform Development living in Belgium.
I’m currently employed as a .NET consultant at RealDolmen, one of Belgium’s leading IT single source providers.

I'm also founding member and board member of the Belgian Metro App Developer Network, a user group focussed on Windows 8 and Windows Phone development. If you're in Belgium feel free to drop by if we're doing an event. http://www.madn.be

Since June 2012 I'm a proud member of Microsoft's Extended Experts Team Belgium. And in February 2013 I became a member of DZone's Most Valuable Bloggers family.

In 2013 I became a book author and wrote "Windows 8 app projects, XAML & C# edition".

In 2014 I received the MVP award for the very first time.

I hope to get feedback from my readers either through comments, mail (nico_vermeir@hotmail.com), twitter, facebook, …

 

mvp

 

mvp

 

 

MeetLogo

 

MVBLogo

mybook

 

Month List