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

A practical guide to MVVM (Light)

by Nico

You don’t have to look very far into the pits of the internet to find that there are still a lot of devs with questions on how to build a Windows / Windows Phone app with the MVVM pattern. In this article I’m going to explain my way of working. The libraries I use, how and why I use them. I hope this will clear some of the doubts others are having and helps you get on the right MVVM track.

What is MVVM?

Let’s start with walking through what MVVM is exactly. Feel free to skip this part if you already know because this has been discussed on almost every tech related website Glimlach

Let’s start with a diagram.


Source: c-sharpcorner.com

In MVVM there are three main parts, the Views, the Model and the ViewModels. The Model are just your basic POCO classes, nothing to fancy in there. The Views are your XAML files, the visual aspect of the application. The ViewModels are classes that get data from your data service classes and shape it into something the view is expecting.

Why these three parts? it’s a matter of seperation of concerns, the View doesn’t need to know where the data is coming from or in what format it’s delivered by the service. The only thing the View cares about is where it can get its data and it assumes that the data will be in the correct format. It gets that data from the ViewModel (or VM in short) through databinding. The View can make the VM do stuff by sending Commands its way, so View and ViewModel can interact with each other. The ViewModel reacts on those commands and requests data from the services, where that data comes from (in-memory, API, whatever, …) doesn’t matter for the VM, as long as it gets what it’s expecting.

Now, why would you use this? As mentioned before, it makes your code much cleaner by seperating the logic out of the View into the VM. It also makes the entire application much easier to unit test. You can just write tests against the ViewModels, since they are just normal .NET classes.

The endless discussion of code behind

There’s a small war among developers going on about MVVM. MVVM states that no code should exist in the code-behind of a view (for example MainPage.xaml.cs). Some people cling onto this statement, others take it as a “if you can”.

Here’s my opinion on the subject: MVVM is a design pattern, meaning that it’s a set of guidelines. Guidelines, as in “not set in stone”. Sometimes you need to jump through a lot of hoops to get something done in the VM while it’s much easier in the View. If you run into such a situation: decide if it’s worth spending time and research into the subject (and blog about it after you find the solution Knipogende emoticon). Another situation is things that have to do with the view. Things like changing a state in the Visual State Manager when switching from landscape to portrait, this is something that you can take to the ViewModel but in my opinion the VSM is pure View business, it has nothing to do with the ViewModel so that’s something I typically put into code behind.

As you can tell, the discussion isn’t really worth it. Just do whatever feels right for you (if you’re working in a team, make sure everyone is on the same page about this).

Let’s get started

Enough chit-chat, let’s get to the practical side of things. For this article I’m going to go with a Windows Phone 8.1 Silverlight project but a lot of the stuff here is applicable to any XAML technology, even ranging back to Windows Phone 7.

We’ll start with a blank slate, a brand new project started from the Blank App template. First thing you need to do when developing an MVVM application is add your MVVM stuff, either by adding a framework like Caliburn or by adding a toolkit with helper classes like MVVM Light (or by building your own of course). My weapon of choice in MVVM is always MVVM Light. Why? Because it’s a toolkit rather than a framework, it leaves a lot of the responsibilities in the hand of the developer. Frameworks like Caliburn rely more on conventions and that’s something I personally do not like. Other people have other preferences over this, so choice whatever feels right for you. For this article I’m using MVVM Light.

Let’s start by adding MVVM Light to the project. As with any good library, it’s on NuGet. If you search for MVVM Light on NuGet you’ll get some results, so what to pick? (I’ve marked the official MVVM Light NuGet packages in the screenshot).

Let’s go over them, top to bottom. The first one is the one I usually use. It adds the MVVM Light libraries to your project, creates a folder for the viewmodels, creates the MainViewModel and ViewModelLocator (more on this in a bit) and instantiates the ViewModelLocator in App.xaml. Quite a lot of work all done for you by the power of NuGet and PowerShell. The second NuGet package just adds the libraries to your project but it doesn’t create any folders or classes. The third package is the same as the second but as a Portable Class Library, use this one if you’re adding ViewModels in a PCL.

I usually go with the first one because of all the initial setup that occurs. Let’s add that package and have a look at the Solution Explorer.

For starters, NuGet added three libraries to the project. Why three? The first one is the actual MVVM Light library, the second one contains a bunch of extras like EventToCommand and SimpleIOC. In case you’re wondering why these are in a separate library, and where that Microsoft.Practices.ServiceLocation lib comes from, here’s Laurent’s answer to that:

“The Extras assembly exists because EventToCommand requires a reference to System.Windows.Interactivity, while ButtonBaseExtensions, RelayCommand, Messenger etc do not need it. Some people are reluctant to add references to assemblies if they can avoid it. So for those people who don't need EventtoCommand, they onlu use the base assembly, and the others who want the whole program can add Extras.

Cheers, Laurent”
Source: http://stackoverflow.com/questions/4740811/why-are-mvvmlight-command-and-mvvmlight-extras-wp7-both-needed

Let’s take a look at the generated code files, starting with MainViewModel (I removed some of the comments for brevity)

Code Snippet
  1. namespace MvvmDemo.ViewModel
  2. {
  3.     public class MainViewModel : ViewModelBase
  4.     {
  5.         public MainViewModel()
  6.         {
  7.             ////if (IsInDesignMode)
  8.             ////{
  9.             ////    // Code runs in Blend --> create design time data.
  10.             ////}
  11.             ////else
  12.             ////{
  13.             ////    // Code runs "for real"
  14.             ////}
  15.         }
  16.     }
  17. }

Not much in there, but there doesn’t need to be. That’s what I like about MVVM Light, it keeps things simple and, well Light Glimlach. ViewModels are defined by creating a class that inherits from ViewModelBase, the name of a ViewModel (or VM in short) doesn’t need to end in “ViewModel” but I tend to do this to make them recognizable. We’ll be discussing the piece of code that’s commented out in a bit.

Next up is the ViewModelLocator class (again, removed some comments for brevity).

Code Snippet
  1. public class ViewModelLocator
  2. {
  3.     /// <summary>
  4.     /// Initializes a new instance of the ViewModelLocator class.
  5.     /// </summary>
  6.     public ViewModelLocator()
  7.     {
  8.         ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
  9.  
  10.         ////if (ViewModelBase.IsInDesignModeStatic)
  11.         ////{
  12.         ////    // Create design time view services and models
  13.         ////    SimpleIoc.Default.Register<IDataService, DesignDataService>();
  14.         ////}
  15.         ////else
  16.         ////{
  17.         ////    // Create run time view services and models
  18.         ////    SimpleIoc.Default.Register<IDataService, DataService>();
  19.         ////}
  20.  
  21.         SimpleIoc.Default.Register<MainViewModel>();
  22.     }
  23.  
  24.     public MainViewModel Main
  25.     {
  26.         get
  27.         {
  28.             return ServiceLocator.Current.GetInstance<MainViewModel>();
  29.         }
  30.     }
  31.     
  32.     public static void Cleanup()
  33.     {
  34.         // TODO Clear the ViewModels
  35.     }
  36. }

So what is the ViewModelLocator? It’s the class that registers all the dataservices and viewmodels in the IOC container (if you don’t know what IOC is, read the next alinea, if you do know what it is you can skip the next part). The ViewModelLocator also provides properties for every ViewModel so we can easily bind a view to a viewmodel. The get part of these properties take the VM instance out of the IOC (again, read the next part for info on IOC) and returns it to the caller. Finally there’s a Cleanup method that you can use to cleanup viewmodels if you need to.

SideStep: IOC

Read this part if you’re not familiar with IOC, feel free to skip this part if you’ve already used IOC.
IOC, or Inversion Of Control, is often used in conjunction with DI or dependency injection. IOC is a technique used to make applications easily extensible and to increase the modularity. These goals can be achieved by using techniques like the Factory Pattern or Dependency Injection. With IOC and DI we can register classes in a so called container. Then, whenever we need one of those registered classes we can fetch the instance from the container instead of instantiating a new one, basically creating a Singleton effect. The big difference with a Singleton is that we can have dependency injection. If one of the classes contains a constructor that takes, for example, a dataservice as parameter and that dataservice is also registered in the container, the DI will inject the dataservice instance into the class with the constructor that takes in a dataservice. More over, we can use interfaces to register classes into the container. If that same class from before takes IDataService as a parameter, the registered instance of a class that implements IDataService will get injected into the constructor. This allows for a more abstract way of working.

Note: this was a basic explanation for IOC / DI. If you really want to get the hang of it, research it and use it, you’ll get it in no time. Some quick links to get you started (with thanks to Glenn Versweyveld for the links)

End of the sidestep: Marching on

MVVM Light has a built in IOC/DI framework called SimpleIoc. It’s exactly as the name implies, a very simple, basic framework but it gets the job done. In case that it wouldn’t fulfill your needs or you feel more comfortable with, for example, AutoFac, it’s really easy to swap SimpleIoc out and another framework in. See my “10 things you might have missed about MVVM Light” article from last year for a quick sample.

Okay, final part of the MVVM Light Powershell magic is something that happened inside the App.xaml. A resource was added to the Application.Resources

Code Snippet
  1. <Application.Resources>
  2.     <local:LocalizedStrings xmlns:local="clr-namespace:MvvmDemo" x:Key="LocalizedStrings" />
  3.     <vm:ViewModelLocator xmlns:vm="clr-namespace:MvvmDemo.ViewModel"
  4.                          x:Key="Locator"
  5.                          d:IsDataSource="True" />
  6. </Application.Resources>

The ViewModelLocator is added as an application resource, so it will get instantiated as soon as the application starts up. That means that all viewmodels and services are registered in the DI container right away. The resource is given a key so we can reference it when we set our datacontext in xaml.

Moving the View

MVVM Light puts the VM in the VM folder by default but the views are just hanging around in the project. If you don’t like this (as I do Glimlach) you can add a View folder and move the MainPage into that folder. Once it’s moved I have the habit of changing the namespace of MainPage to reflect the folder structure. This needs to happen in two places, xaml and code behind. In xaml find this line (it should be at the top)

Code Snippet
  1. x:Class="MvvmDemo.MainPage"

and change it to

Code Snippet
  1. x:Class="MvvmDemo.View.MainPage"

In code behind change the namespace to

Code Snippet
  1. namespace MvvmDemo.View

Right now, your application will compile perfectly but you will get a NavigationFailedException when launching. Open up the WMAppManifest.xml. On the Application UI tab is a textbox that says Navigation Page: MainPage.xaml. Navigating in Silverlight apps is still done using strings, so the compiler is happy here but at runtime the navigation target isn’t found at this location. Change it from MainPage.xaml to /View/MainPage.xaml and see if it works. If you entered the correct folder path the app should start.

Hooking up the View

Let’s get to the interesting part. We’re now ready to hook our view up on the viewmodel. This can be done from code behind or from XAML. I prefer the XAML way because it gives you some intellisense when binding to properties on the viewmodel, since the XAML designer knows of the datacontext if it’s defined in XAML.

This is what we need to add to the opening tag of a page to set the datacontext

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

This is the full tag for reference:

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="MvvmDemo.View.MainPage"
  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 Main,
  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">

If you don’t want to do it from XAML, it’s very easy to set it via Blend as well.

Open MainPage.xaml in Blend. Select PhoneApplicationPage in the Objects & Timeline pane.

In the properties pane, search for the DataContext Property and click on the white square next to it, select “Create databinding”

In the dialog that will popup, you’ll see the Locator key that we declared in App.xaml, Blend can interpret those resources and help you with binding to them. Select the Locator and you’ll see the Main property that is defined inside the ViewModelLocator (remember, the property that gets the MainViewModel instance from the container and returns it to the caller). Select that property and click OK, your binding is set!

Small thing about Blend: It’s AWESOME! period. If you don’t know how to use it, learn it. Learn to use it and you’ll automatically love it. Your apps will look much better and once you get the hang of using design time data you’ll get your design done much faster.

Adding our first binding

Let’s get some binding done! We’ll bind the title of the page to a property on the ViewModel just to get started. In the MainViewModel, Create a simple string autoproperty

Code Snippet
  1. public string Title { get; set; }

We’ll use the MainViewModel’s constructor to give this property some data. (line 3)

Code Snippet
  1. public MainViewModel()
  2. {
  3.     Title = "Hello World!";
  4.  
  5.     ////if (IsInDesignMode)
  6.     ////{
  7.     ////    // Code runs in Blend --> create design time data.
  8.     ////}
  9.     ////else
  10.     ////{
  11.     ////    // Code runs "for real"
  12.     ////}
  13. }

Now onto the view, find the TextBlock for the page title and add the binding statement to the Text attribute (this can be done from Blend, just like the datacontext property, select the textblock, find the text property and add data binding)

Code Snippet
  1. <TextBlock Margin="9,-7,0,0"
  2.            Style="{StaticResource PhoneTextTitle1Style}"
  3.            Text="{Binding Title}" />

The Text property now contains a Binding statement. This is always set between curly braces, followed by the word Binding and the name of the property we’re binding to. At runtime the CLR will try to find a property with that name in the datacontext of the TextBlock, since we’re not specifying a DataContext on the TextBlock it will take that of its parent control, that way we’ll finally reach the MainViewModel where the Title property is waiting for us. Run the app and behold the wonders of databinding in an MVVM scenario.

Now this works but if we were to change the Title property as it is right now, it wouldn’t reflect on the page. A bound property isn’t monitored or polled for changes, we need to trigger some sort of event to tell the subscribers that a property has changed and that they need to refresh their binding. Usually this is done by implementing INotifyPropertyChanged and calling the OnPropertyChanged event in the property’s setter. In the case of MVVM the INotifyPropertyChanged interface is already implemented in the ViewModelBase class, so all we have left to do is raise the event (or call a method that raises the event, that method is called RaisePropertyChanged and sits in the ViewModelBase) from the property’s setter.

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

We check if the property has really changed to avoid refreshing bindings when it’s not needed, if it does change we raise the event. According to the INotifyPropertyChanged interface we need to pass the property name as a string. MVVM Light’s ViewModelBase has an overload that takes a Func<string> so we can rely on intellisense to get the name of the property right. And with this we have a real databinding that will update the view when changed. Also, if you open MainPage in Blend now, you’ll notice that the binding is executed in design time as well. That’s one of Blend’s biggest strengths.

Using real fake data

Okay, so we now have databinding all set up, our MVVM structure is in place. Let’s build something that resembles an actual app. Create a Model folder in your project and add a Person class to it.

Code Snippet
  1. public class Person
  2. {
  3.     public string Picture { get; set; }
  4.     public int Age { get; set; }
  5.     public string Name { get; set; }
  6.     public string Company { get; set; }
  7.     public string Email { get; set; }
  8.     public string Phone { get; set; }
  9. }

Now to get some data I’ve used a website called json-generator to generate 15 instances of this class in Json format. You can download the JSON file I’ve used here

I placed the json in a static field in a static public class so my dataservice can easily get to it. I use this to simulate what could be a REST call in a real application. (if you want to know more about creating and calling REST services, read my article)

Add a folder called Services to the project and add an interface called IDataService.

Code Snippet
  1. public interface IDataService
  2. {
  3.     IEnumerable<Person> GetAll();
  4.     IEnumerable<Person> Get(Func<Person, bool> predicate);
  5.     Person GetByName(string name);
  6. }

The interface defines methods to fetch all the persons, to get a filtered set of persons by passing a predicate into a Where clause or fetch a specific person by name.

We’ll end up with two implementations of this interface. Let’s start with the first one, this one will be used at runtime and will query the actual service (the hardcoded JSON in this case, just assume it’s a call to a REST service). The first implementation is easy, the constructor fetches and deserializes the json. The methods then query that resultset.

Code Snippet
  1. public class DataService : IDataService
  2. {
  3.     private IEnumerable<Person> _persons;
  4.  
  5.     public DataService()
  6.     {
  7.         _persons = JsonConvert.DeserializeObject<IEnumerable<Person>>(Data.Data.Json);
  8.     }
  9.  
  10.     public IEnumerable<Person> GetAll()
  11.     {
  12.         return _persons;
  13.     }
  14.  
  15.     public IEnumerable<Person> Get(Func<Person, bool> predicate)
  16.     {
  17.         return _persons.Where(predicate);
  18.     }
  19.  
  20.     public Person GetByName(string name)
  21.     {
  22.         return _persons.FirstOrDefault(person => person.Name == name);
  23.     }
  24. }

Very basic data service, but enough to get my point across. Now it’s time to revisit the ViewModelLocator. When you look at the constructor of the ViewModelLocator you’ll notice that it contains a block of code that’s commented out.

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.     ////}
  15.  
  16.     SimpleIoc.Default.Register<MainViewModel>();
  17. }

That piece of code is exactly what we need. Why? Because it checks if the code is being executed in runtime or in design time. As I’ve mentioned before, the Blend and Visual Studio designers execute the code whenever a page is loaded into the designer. We can use that to hook up dummy data. The ViewModelBase class from MVVM Light contains a static boolean that tells us if we’re in design mode. We can use this to either register DataService in the container or a design time version of DataService (which we’ll build in a minute).

Uncomment the code so it looks like this (don’t worry about the DesignDataService error, the class doesn’t exist yet but it’s the next step.

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.     }
  15.  
  16.     SimpleIoc.Default.Register<MainViewModel>();
  17. }

In the Services folder, add a class called DesignDataService and make it implement IDataService.

Code Snippet
  1. public class DesignDataService : IDataService
  2. {
  3.     private List<Person> _persons;
  4.  
  5.     public DesignDataService()
  6.     {
  7.         _persons = new List<Person>();
  8.         Random rnd = new Random();
  9.  
  10.         for (int i = 0; i < 10; i++)
  11.         {
  12.             Person person = new Person
  13.             {
  14.                 Age = rnd.Next(10, 60),
  15.                 Company = "Design time company",
  16.                 Email = "design@time.com",
  17.                 Name = "Design time person " + i,
  18.                 Phone = "+1 (846) 597-3140",
  19.                 Picture = "http://files.softicons.com/download/tv-movie-icons/doctor-who-icons-by-rich-d/png/48/Tardis%203.png"
  20.             };
  21.  
  22.             _persons.Add(person);
  23.         }
  24.     }
  25.     public IEnumerable<Person> GetAll()
  26.     {
  27.         return _persons;
  28.     }
  29.  
  30.     public IEnumerable<Person> Get(Func<Person, bool> predicate)
  31.     {
  32.         return _persons.Where(predicate);
  33.     }
  34.  
  35.     public Person GetByName(string name)
  36.     {
  37.         return _persons.First();
  38.     }
  39. }

I use a for loop to create 10 design time persons. Note that the GetByName method just returns the first person in the list. For design time data it doesn’t matter if the correct data is returned, we’re only using this data to get the visual aspect of the application right. Verify that the app still compiles and let’s get this thing injected.

Open the MainViewModel. Add a field for the IDataService and add IDataService as a parameter for the constructor.

Code Snippet
  1. private readonly IDataService _dataService;
  2. public MainViewModel(IDataService dataService)
  3. {
  4.     _dataService = dataService;
  5.     Title = "Hello World!";
  6. }

This is where constructor injection will come into play. SimpleIoc will inject the registered implementation if IDataService right here in the constructor, if you want to see this set a breakpoint in the constructor, open the app and inspect the parameter.

Now I want a property that contains the persons and bind this to some sort of list element so we get a nice, scrollable overview of persons. The perfect collection for bindable properties is an ObservableCollection. It notifies subscribers whenever an item is added so that those newly added items are shown immediately. Add the property to the MainViewModel

Code Snippet
  1. private ObservableCollection<Person> _persons;
  2. public ObservableCollection<Person> Persons
  3. {
  4.     get { return _persons; }
  5.     set
  6.     {
  7.         if (_persons == value) return;
  8.         _persons = value;
  9.         RaisePropertyChanged(() => Persons);
  10.     }
  11. }

We’re going to use the constructor of the MainViewModel to get some data in.

Code Snippet
  1. public MainViewModel(IDataService dataService)
  2. {
  3.     _dataService = dataService;
  4.     Title = "Hello World!";
  5.  
  6.     IEnumerable<Person> persons = _dataService.GetAll();
  7.     Persons = new ObservableCollection<Person>(persons);
  8. }

The constructor of ObservableCollection<T> has an overload that takes in an IEnumerable<T> that can be used to seed the collection.

Blending it in

Let’s dive into Blend and get that design time data to work. Open MainPage.xaml in Blend. In the Data tab in Blend you’ll notice that MainViewModel shows up as Data Context, if you expand the tree structure you’ll find your ObservableCollection (if you don’t see it, switch back to Visual Studio and Build the solution, Blend doesn’t always update unless you build the project). Take the Persons property there and drag/drop it onto the design view (make sure MainPage.xaml is opened in design). When dragging over the design you should see this message appear.

Release the mouse button and a ListBox will be created and its ItemsSource wil lbe bound to that list on our MainViewModel. But it doesn’t look quite right.

This is common in Blend and is easily fixed, right-click the ListBox, go to Layout and select “Reset all”

Note: this is currently a ListBox, we are advised by Microsoft to use LongListSelector instead of ListBox for performance reasons. To change this, go into the xaml and change <ListBox… to <phone:LongListSelector.. Blend will keep working just like it’s doing now. For this article I’m just going to stick to ListBox but the way of working is the same.

We have a list of design time items now. Let’s run the app and see how it looks.

Notice how the data is different? The ViewModelLocator has registered the real DataService into the container so we’re now getting our real data instead of the design time data.

This doesn’t look very well, let’s see what we can do to change that. Blend makes changing item templates really easy, right-click the Listbox > “Edit Additional Templates” > “Edit Generated items (ItemTemplate)” > “Edit Current”

Have a look at the Objects & Timeline pane, you’ll see that it’s changed and shows the itemTemplate

From here you can create your entire layout, drag and drop properties from the Data tab onto the elements to create databindings. After about a minute I came up with this result.

The XAML for the itemtemplate:

Code Snippet
  1. <DataTemplate x:Key="PersonTemplate">
  2.     <Grid Margin="0,0,0,12">
  3.         <Grid.ColumnDefinitions>
  4.             <ColumnDefinition Width="Auto" />
  5.             <ColumnDefinition />
  6.         </Grid.ColumnDefinitions>
  7.         <Border Width="100"
  8.             Height="100"
  9.             HorizontalAlignment="Left"
  10.             VerticalAlignment="Top"
  11.             BorderBrush="Black"
  12.             BorderThickness="1">
  13.             <Image Source="{Binding Picture}" />
  14.         </Border>
  15.         <StackPanel Grid.Column="1">
  16.             <TextBlock Style="{StaticResource PhoneTextLargeStyle}" Text="{Binding Name}" />
  17.             <TextBlock Style="{StaticResource PhoneTextSubtleStyle}" Text="{Binding Company}" />
  18.         </StackPanel>
  19.     </Grid>
  20. </DataTemplate>

Result in runtime:

Splitting this post + Conclusion

I’m going to split this up in two posts as this one’s long enough already and my keyboard is getting tired Glimlach

Part two will focus on selecting a person from the list, navigating to a detail page, fetching and showing the details. Expect it to show up some time next week (I’ll update this post as well as soon is its ready).

In this first part I’ve discussed what MVVM was and why you should do it. I’ve shown you how I use MVVM Light and walked through the setup. We’ve also discussed design-time data and how Blend combined with this designtime data can help you getting a nice UI in a fast way.

The code for this first part can be found on my OneDrive.


Tags:

.Net | Data | MVVM Light | Patterns | WP7 | WP8 | WinRT | 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

Xaml Styler for Visual Studio 2013

by Nico

Xaml Styler is a free Visual Studio 2012 extension available from the gallery. I’ve been using this extension for quite some time now and I’m really happy with how it styles my XAML code. Unfortunately the extension isn’t compatible with Visual Studio 2013.

Luckily for us, the extension is on Codeplex. I’ve downloaded the code, referenced the new Visual Studio SDK and recompiled it. It seems to be working fine with Visual Studio 2013 now.

I’ve uploaded the binaries to my Skydrive folder so that everyone can enjoy the extension in Visual Studio 2013 until the original author of the plug-in creates official Visual Studio 2013 support.

Be aware, this version isn’t thoroughly tested by anyone! I’ve compiled it, installed it and I’m currently using it. I haven’t ran into any problems yet but that doesn’t mean that it won’t have any problems. These binaries are supplied as-is.

Download from Skydrive

Gallery link

Original Codeplex page


Tags:

.Net | WP7 | WP8 | WPF | WinRT | Windows 8 | XAML

ViewModelBackstack for when you navigate to the same page

by Nico

When working on my comic application for Windows Phone I encountered a problem that I’ve had in the past and have heard others ran into as well. When on the detailspage of a comic character I have a list of enemies of that character. Those enemies are clickable to load their details. Nothing hard there, but both the first character and its enemies are of the same type and they use the same view and viewmodel to show their data. This isn’t hard to do, the difficult part is using the phone’s back button. After navigating to the same CharacterDetailPage 4 times I would expect the back button to take me back through all the characters I’ve viewed.

I was trying to use OnNavigatedTo and OnNavigatedFrom events but apparently those do not fire when navigating to the same page. After a bit of tinkering I came up with a ViewModelBackstack class that does the trick.

I’ve uploaded the class and a sample project to GitHub and I’ve created a NuGet package for everyone to use (my very first public package, hooray!). In this post I’ll walk through the sample project to explain how it works.

First of all, if you want to add the package to your solution, search for ViewModelBackstack on NuGet or use the command line

Install-Package ViewModelBackstack

Once that’s setup start building your application, MVVM style (the sample application uses MVVM Light, but ViewModelBackstack should work with all the other ones out there).

The sample application

The sample application is a basic one, it has two pages, a MainPage and a GuidPage. The MainPage only contains some text and a button to navigate to the second page. The GuidPage contains a textblock that is bound to a property on the viewmodel, and a button that simulates navigating to the same page again but loading in different data.

The scenario is this:

MainPage > GuidPage > GuidPage > GuidPage > …

MainVM > GuidVM > GuidVM > GuidVM > …

Follow it the other way around to know how the back button will respond.

The ViewModelBackstack class

ViewModelBackstack is a static class, and not a very big one.

Code Snippet
  1. public static class ViewModelBackStack
  2. {
  3.     private static Dictionary<string, string> _viewModelStack;
  4.  
  5.     public static void Add(string key, object value)
  6.     {
  7.         if (_viewModelStack == null)
  8.             _viewModelStack = new Dictionary<string, string>();
  9.  
  10.         _viewModelStack.Add(key, JsonConvert.SerializeObject(value));
  11.     }
  12.  
  13.     public static object Take<T>(string key)
  14.     {
  15.         string toReturn = _viewModelStack[key];
  16.         Delete(key);
  17.  
  18.         return JsonConvert.DeserializeObject<T>(toReturn);
  19.     }
  20.  
  21.     public static bool TryTake<T>(string key, out T value)
  22.         where T : class
  23.     {
  24.         try
  25.         {
  26.             value = JsonConvert.DeserializeObject<T>(_viewModelStack[key]);
  27.             Delete(key);
  28.  
  29.             return true;
  30.         }
  31.         catch (Exception)
  32.         {
  33.             value = null;
  34.             return false;
  35.         }
  36.     }
  37.  
  38.     public static bool ContainsKey(string key)
  39.     {
  40.         if (_viewModelStack == null)
  41.             return false;
  42.  
  43.         return _viewModelStack.ContainsKey(key);
  44.     }
  45.  
  46.     public static void Delete(string key)
  47.     {
  48.         _viewModelStack.Remove(key);
  49.     }
  50.  
  51.     public static void Replace(string key, object newValue)
  52.     {
  53.         _viewModelStack[key] = JsonConvert.SerializeObject(newValue);
  54.     }
  55.  
  56.     public static bool CanGoBack()
  57.     {
  58.         if (_viewModelStack == null)
  59.             return false;
  60.  
  61.         return _viewModelStack.Count > 0;
  62.     }
  63.  
  64.     public static T GoBack<T>()
  65.     {
  66.         var toReturn = _viewModelStack.Last();
  67.         _viewModelStack.Remove(toReturn.Key);
  68.  
  69.         return JsonConvert.DeserializeObject<T>(toReturn.Value);
  70.     }
  71. }

It contains a Dictionary<string, string> that will hold the instances of the viewmodels. The instances are serialized into JSON strings with Json.net. This to save memory and avoid reference issues.

There are some methods in there to manually take out a specific instance or to delete one. But more importantly are the CanGoBack() and GoBack() methods. Let’s have a look at how to use this.

Usage

In the GuidViewModel’s constructor we start listening for a message, when that message arrives we load in new data (in this case, generate a new GUID) GuidString is a normal property that calls RaisePropertyChanged from the setter.

Code Snippet
  1. public GuidViewModel()
  2. {
  3.     Messenger.Default.Register<GenerateNewGuidMessage>(this, msg => GenerateGuid());
  4. }
  5.  
  6. private void GenerateGuid()
  7. {
  8.     GuidString = Guid.NewGuid().ToString();
  9. }

Next is the command that is bound to the button on the page, this is a RelayCommand that will call the LoadNewData method

Code Snippet
  1. private void LoadNewData()
  2. {
  3.     if (ViewModelBackStack.ContainsKey(GuidString))
  4.         ViewModelBackStack.Replace(GuidString, this);
  5.     else
  6.         ViewModelBackStack.Add(GuidString, this);
  7.  
  8.     Messenger.Default.Send(new GenerateNewGuidMessage());
  9. }

The LoadNewData method will check if the ViewModelBackStack already contains the key we use (each instance needs a unique key, we’re using the GUID in this case). If it’s already there, replace it, if not add it to the backstack. After that, send the message to generate new data.

Note that we’re not actually navigating away from the page, since the NavigationService doesn’t actually navigate when you try going to the same page there’s really no use in trying.

The final step is intercepting the back button press and using it load in a previous instance of the GuidViewModel. We need to do this in the code-behind of the page, since we need to cancel the navigation there (by default, when pressing the back button here it would just take us back to MainPage, so navigation needs to be cancelled).

Code Snippet
  1. protected override void OnBackKeyPress(CancelEventArgs e)
  2. {
  3.     if (ViewModelBackStack.CanGoBack())
  4.     {
  5.         DataContext = ViewModelBackStack.GoBack<GuidViewModel>();
  6.         e.Cancel = true;
  7.         return;
  8.     }
  9.  
  10.     base.OnBackKeyPress(e);
  11. }

OnBackKeyPress can be overriden from PhoneApplicationPage base class. If the ViewModelBackStack can go back we take out the most recent record in the dictionary, deserialize it to T, set that result as datacontext and we’re done. We can cancel the navigation by setting e.Cancel to true. Once the ViewModelBackStack is empty the app will return to MainPage.

Wrap up

So that’s about it. I’m currently building a Windows Phone app that uses the ViewModelBackStack, so there could be some changes coming in the next few weeks, or it might just prove to work perfectly as-is.

Feel free to fork the repo on GitHub and send pull requests if you can enhance / improve upon the project, props will be given Glimlach.


Tags:

.Net | Devices | MVVM Light | NuGet | PCL | WP7 | WP8

Don’t forget the system tray in your WP8 app

by Nico

The system tray in Windows Phone 8 is the small bar at the top where the clock, signal strength, connectivity icons, etc. reside. In most apps I’ve used developers tend to do one of two things there:

  • leave it
  • hide it

An example here is Microsoft’s Facebook app (yes, even the first party apps do this), take a look

This is a pretty decent looking app (yes it violates a bunch of “Modern UI” guidelines but it does look decent). However, the black system tray at the top of the screen breaks the experience. It feels like the app lies on top of the homescreen, while this is actually true it’s a better user experience to suck the user completely into the application.

Another option for the Facebook app would be to hide the system tray, this won’t break the experience for the user on the visual side.

But this solution has another downside, the Facebook app needs an active internet connection to work, suppose the app throws an error saying that your internet connection is down, what’s your first reaction? You check the signal strength and / or wifi connectivity icon, and where do those live? In the system tray that is hidden now, so the user needs to exit the app to check the system tray (same goes for checking the time).

Only hide the system tray when your app absolutely requires it, like a game that needs all the screen estate it can get.

So let’s try a third solution, something a lot of Windows Phone developers tend to forget or don’t know is possible, we can style the system tray. This is what the Facebook app could look like

By simply giving the system tray the same color as the header bar of the app we’ve give the app a little extra while still having a visible system tray.

I used this approach in my Traffic Chat app

Same story in this app, it looks much more like a part of the OS instead of “just an app”.

Let’s do it!

It’s actually very easy to get this done.

In your Windows Phone application, navigate to the App.xaml page. In that page there should be an Application.Resources tag. As you might (should) know, we can define application wide styles here, if we don’t provide a key to a style it applies to all controls of the specified type throughout the app. Sounds easy enough, let’s do it.

Code Snippet
  1. <Style TargetType="phone:PhoneApplicationPage">
  2.     <Setter Property="shell:SystemTray.BackgroundColor" Value="Red" />
  3.     <Setter Property="shell:SystemTray.ForegroundColor" Value="Green" />
  4. </Style>

The style has a target type of PhoneApplicationPage, the class that is used by all pages in a Windows Phone app. We set the backgroundcolor to Red and the Foregroundcolor to Green, this will look very pretty right? Glimlach

If we run the app now you’ll see that nothing has changed. A downside of this is that not providing a key doesn’t work for the PhoneApplicationPage, so we’ll need to name the style and apply it to every page in the application.

Change the above code to this (add a key, name it whatever you want)

Code Snippet
  1. <Style x:Key="DefaultPageStyle" TargetType="phone:PhoneApplicationPage">
  2.     <Setter Property="shell:SystemTray.BackgroundColor" Value="Red" />
  3.     <Setter Property="shell:SystemTray.ForegroundColor" Value="Green" />
  4. </Style>

And on every page that you want to style the systemtray, apply the style (line 15 in this code block).

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

If we run the app now we’ll get a “beautiful” styled system tray.

 

Conclusion

Styling the system tray is something that is often overlooked. Spend some time on this, it’ll make your app look even better without annoying your users with a hidden system tray. It’s easy to do and doesn’t take a lot of time.

Download the Green/Red system tray app from my SkyDrive


Tags:

.Net | Devices | WP7 | WP8 | XAML

Run your WP8 app on two emulators simultaneously

by Nico

I’m currently working on a Windows Phone 8 project that requires two devices. Those devices talk to each other through a SignalR service. Thanks to Hyper-V I’m able to test/debug this project on two instances of the Windows Phone 8 emulator (I usually pick the WVGA and WVGA 512MB versions). What I used to do is deploy the XAP to one emulator and debug it on the second. I need to do this every time I change the app, I got bored of doing this manually so it was about time to get this automated.

Since Visual Studio 2012 builds the app everytime its codebase changes I can use the post-build script to do this, after all the app should only install itself on both emulators when it’s changed (I did spent time looking for a solution to let the script run every time I hit the debug button but it looks like there’s no way to do this in VS2012).

The point of the post-build script is to fire up the emulator when needed, deploy the app and run it. Visual Studio 2012 debug will fire up the second emulator, deploy the app there and launch it with debug, meaning that only one emulator will have a debugger attached.

Choosing the emulator for the script

Microsoft has provided a command line tool for deploying xap files, both onto a device and onto the emulators. Before we can start using it we’ll need to know the correct index of the emulator that we want the script to use. Copy-paste this script into a textfile and save as a .bat file, double click it and you should see a list of all available emulators on your machine (provided that you have the Windows Phone 8 SDK installed of course).

Code Snippet
  1. cd "%ProgramFiles(x86)%\Microsoft SDKs\Windows Phone\v8.0\Tools\XAP Deployment"
  2. XapDeployCmd.exe /EnumerateDevices
  3. pause

XapDeployCmd.exe is the commandline tool for everything related to XAP deployments. More information on the tool can be found on MSDN

Choose the emulator of your choose from the list and remember its index.

Building the script

Time to start building the script. In your Windows Phone 8 project, go to the project properties to the Build Events tab. In the Post-build event command line box enter this script.

Code Snippet
  1. cd %ProgramFiles(x86)%\Microsoft SDKs\Windows Phone\v8.0\Tools\XAP Deployment
  2. XapDeployCmd.exe /installlaunch $(TargetDir)$(ProjectName)_$(ConfigurationName)_$(PlatformName).xap /targetdevice:1

The first line of the script navigates the command line to the folder where the XapDeployCmd lives (this is the default install path, the tool comes with the WP8 SDK). The second line launches the tool and passes the necessary parameters. the installaunch parameter states that the app should install (or update) the app and launch it when finished. After the installaunch parameter we need to state the path to the xap file, by default (when using the debug configuration in VS2012) it’s in the bin/debug folder and is called something like MyWPApp_debug_anycpu.xap. To make the script easy to transfer over I’ve used variables instead of hardcoding the path and the xap name. Here’s a quick rundown.

Variable Meaning
$(TargetDir) the full path to the outputdirectory (for example: c:\users\nico\documents\Projects\MyWPApp\bin\debug\)

Keep in mind that the last “\” is always included when using this variable
$(ProjectName) The name of the project (didn’t see that one coming, did you? Glimlach) (for example: MyWPApp)
$(ConfigurationName) The used configuration, for example ”release” or “debug”
$(PlatformName) The selected CPU architecture, for example “AllCpu”, “ARM”, “x86”

With these powers variables combined we get the full path to the xap file. The last parameter specifies the to use emulator by passing in the index that we determined at the beginning of this post.

And that’s it. Rebuild your solution and watch the emulator start app, deploy and launch your app. Now every time that you change the code of the app and hit the debug button it will build and deploy to both emulators. One of the emulators should have those debug numbers on the side, making it easy to recognize which one has the debugger attached.

Conclusion

Using a very simple post-build script and the in the WP8 included XapDeployCmd tool it’s very easy to deploy an application to two devices simultaneously. This isn’t needed very often but when building something that connects users to each other (like a chat application or a multiplayer game) it can save you quite some hassle. Just make sure that your script uses another emulator version than Visual Studio 2012.

 


Tags:

.Net | Devices | WP7 | WP8 | msbuild

Extending the Windows Phone pivot

by Nico

As I was working on a Windows Phone 8 project I needed a pivot that could hide its title, giving back some screen real-estate when needed. The basic pivot that is included in the Windows Phone SDK doesn’t have this kind of behavior so it was a great opportunity to try out custom controls in Windows Phone. I’ve build custom controls in XAML before but never based on an existing one, so fun times ahead. Let me start by showing a side-by-side comparison between both views of my pivot.

don’t mind the overlapping textblock and button, point is that when the button is clicked, the title of the pivot disappears.

Building a XAML custom control

It’s quite easy to build a custom control in XAML as long as you follow the guidelines. It requires you to add a folder called Themes and in the folder a file called generic.xaml. The generic.xaml file is a resource dictionary, no code behind file is needed. Do follow the naming conventions exactly or your control won’t work. Next step is adding a class that inherits from ContentControl (or a control that already inherits from ContentControl). The project for my ExtendedPivot looks like this

The project type is a WP8 class library containing two custom controls, one for the pivot and one for the pivot items.

Extending the pivot

Since I only want to add a functionality to an existing control, the Pivot, my ExtendedPivot class inherits from Pivot instead of CustomControl.

Code Snippet
  1. publicclassExtendedPivot : Pivot
  2. {
  3.     publicstaticreadonlyDependencyProperty HeaderVisibilityProperty =
  4.         DependencyProperty.Register("HeaderVisibilityProperty", typeof (Visibility), typeof (ExtendedPivot), newPropertyMetadata(null));
  5.  
  6.     publicVisibility HeaderVisibility
  7.     {
  8.         get { return (Visibility)GetValue(HeaderVisibilityProperty); }
  9.         set { SetValue(HeaderVisibilityProperty, value); }
  10.     }
  11.  
  12.     public ExtendedPivot()
  13.     {
  14.         DefaultStyleKey =  typeof(ExtendedPivot);
  15.     }
  16. }

We’ll start with the constructor, Line 14 is necessary when developing a custom control, it sets the style of the control to the style defined in generic.xaml (we’ll get to that style in a minute). Lines 6 – 10 are a property that will be used by the DependencyProperty. The DependencyProperty (lines 3-4) is a property that we can bind a value to when using the control in a project, it might seem a bit overwhelming at first but there’s a great snippet in VS2012 to easily write them. Basically, the parameters for the Register function are a name, the type of the property, the owner type (type of the control where you’re declaring the DP) and some metadata.

The get and set method of the normal property use the DP to get and set values through databinding.

generic.xaml

This is the style for the ExtendedPivot as declared in generic.xaml

Code Snippet
  1. <Style TargetType="local:ExtendedPivot">
  2.     <Setter Property="Margin" Value="0" />
  3.     <Setter Property="Padding" Value="0" />
  4.     <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}" />
  5.     <Setter Property="Background" Value="Transparent" />
  6.     <Setter Property="ItemsPanel">
  7.         <Setter.Value>
  8.             <ItemsPanelTemplate>
  9.                 <Grid />
  10.             </ItemsPanelTemplate>
  11.         </Setter.Value>
  12.     </Setter>
  13.     <Setter Property="Template">
  14.         <Setter.Value>
  15.             <ControlTemplate TargetType="local:ExtendedPivot">
  16.                 <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
  17.                     <Grid.RowDefinitions>
  18.                         <RowDefinition Height="Auto" />
  19.                         <RowDefinition Height="Auto" />
  20.                         <RowDefinition Height="*" />
  21.                     </Grid.RowDefinitions>
  22.                     <Grid Grid.RowSpan="3" Background="{TemplateBinding Background}" />
  23.                     <ContentControl Grid.Row="0"
  24.                                     Margin="24,17,0,-7"
  25.                                     HorizontalAlignment="Left"
  26.                                     Content="{TemplateBinding Title}"
  27.                                     ContentTemplate="{TemplateBinding TitleTemplate}"
  28.                                     Visibility="{TemplateBinding HeaderVisibility}" />
  29.                     <primitives:PivotHeadersControl x:Name="HeadersListElement" Grid.Row="1" />
  30.                     <ItemsPresenter x:Name="PivotItemPresenter"
  31.                                     Grid.Row="2"
  32.                                     Margin="{TemplateBinding Padding}" />
  33.                 </Grid>
  34.             </ControlTemplate>
  35.         </Setter.Value>
  36.     </Setter>
  37. </Style>

Basically, I’ve created a xaml page in some very basic Windows Phone project, right-clicked it, selected Edit Template > Edit a copy. This gives you a copy of the template for the Pivot. I copied that template in the generic.xaml style. The ContentControl at Lines 23-28 show the title in the pivot. I added the Visiblity property here and bound it to the HeaderVisibility property in the ExtendedPivot class. To bind a property in a style you need to use the TemplateBinding keyword instead of the normal Binding one.

Don’t forget to set TargetType to the type of your custom control.

Using the custom control in an app

The control is ready, now it’s time to use it. Create a new Windows Phone app and reference the project or DLL of the custom control. This is the MainPage of the sample app.

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="ExtendedPivot.MainPage"
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.                             xmlns:control="clr-namespace:ExtendedPivot.Control;assembly=ExtendedPivot.Control"
  5.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  7.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  8.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  9.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"
  10.                             FontSize="{StaticResource PhoneFontSizeNormal}"
  11.                             Foreground="{StaticResource PhoneForegroundBrush}"
  12.                             Orientation="Portrait"
  13.                             SupportedOrientations="Portrait"
  14.                             shell:SystemTray.IsVisible="True"
  15.                             mc:Ignorable="d">
  16.  
  17.     <!--  LayoutRoot is the root grid where all page content is placed  -->
  18.     <Grid x:Name="LayoutRoot" Background="Transparent">
  19.         <!--  Pivot Control  -->
  20.         <control:ExtendedPivot HeaderVisibility="{Binding Visibility}" Title="MY APPLICATION">
  21.             <control:ExtendedPivotItem Header="item 1">
  22.                 <Grid>
  23.                     <TextBlock Text="item1" />
  24.                     <Button Click="ButtonBase_OnClick" Content="button" />
  25.                 </Grid>
  26.             </control:ExtendedPivotItem>
  27.  
  28.             <control:ExtendedPivotItem Header="item 2">
  29.                 <TextBlock Text="item2" />
  30.             </control:ExtendedPivotItem>
  31.         </control:ExtendedPivot>
  32.     </Grid>
  33. </phone:PhoneApplicationPage>

Line 4 defines the namespace that holds the ExtendedPivot. Line 20 puts the control on the actual page. Notice that we bind the HeaderVisibility property of our control. I defined the datacontext of this page in code behind to be of type MainViewModel. MainViewModel implements INotifyPropertyChanged and only holds one property of type Visibility, that property is bound to the ExtendedPivot’s HeaderVisibility.

The Button in the pivot will switch the HeaderVisibility between Collapsed and Visible, this happens in the code behind of this page.

Code Snippet
  1. publicpartialclassMainPage : PhoneApplicationPage
  2. {
  3.     privateMainViewModel _mainViewModel;
  4.  
  5.     // Constructor
  6.     public MainPage()
  7.     {
  8.         InitializeComponent();
  9.  
  10.         _mainViewModel = newMainViewModel();
  11.  
  12.         DataContext = _mainViewModel;
  13.     }
  14.  
  15.     privatevoid ButtonBase_OnClick(object sender, RoutedEventArgs e)
  16.     {
  17.         if (_mainViewModel.Visibility == Visibility.Collapsed)
  18.         {
  19.             _mainViewModel.Visibility = Visibility.Visible;            
  20.         }
  21.         else
  22.         {
  23.             _mainViewModel.Visibility = Visibility.Collapsed;          
  24.         }
  25.     }
  26. }

Not really the best way of writing a Windows Phone app but it’s just for making the point Glimlach

Conclusion

Extending a Windows Phone control isn’t hard as long as you follow the naming conventions, adding some extra functionality is as easy as copying the xaml template and adding some dependency properties.

The sample code can be found on my SkyDrive

 


Tags:

.Net | Binding | Devices | WP7 | WP8 | XAML

10 things you might have missed about MVVM Light

by Nico

Ever since I started playing with XAML based technologies (which actually isn’t that long ago) I’ve been looking into the MVVM (Model – View – ViewModel) pattern. I stumbled across MVVM Light pretty soon and liked the way it worked. Turns out I’m not the only one that likes it, there’s a whole set of developers, both hobby and professional, that really love this set of libraries. MVVM Light is, according to the author, not a framework but a set of libraries that take care of the plumbing to set up an MVVM structure and provide some extra helper classes to make life easier.

MVVM Light has changed a lot in its history, some elements were dragged out, others dragged in. Fact remains that it’s a fast, easy to use and lightweight framework. The author, Laurent Bugnion, does a great job of listening to the people that use MVVM Light, incorporating requested features and helping developers out. While talking to some of my fellow developers I’ve noticed a few times that there are certain elements of MVVM Light that others hadn’t heard of, and the same goes in the other direction. I’ve learned a lot of new things about MVVM Light just from talking with other users. Thinking about that gave me the idea of this blogpost and since those “10 things about…” posts seem to be popular, this was my chance. So here are my top 10 hidden gems of MVVM Light that you might have missed.

1. The MVVM Light installer

This one might seem a bit obvious, but in this NuGet driven world we would forget the added benefit of an installer. MVVM Light has an MSI installer that not only installs the binaries on your drive but it also provides project and itemtemplates in Visual Studio, along with a list of snippets. In case the Visual Studio 2012 update 2 removed your templates, reinstall the VSIX from C:\Program Files (x86)\Laurent Bugnion (GalaSoft)\Mvvm Light Toolkit\Vsix that should put the project templates back in place.

2. Constructor injection

This one is just awesome, and is actually a feature that can be found in most DI frameworks. MVVM Light uses SimpleIoc to register viewmodels and service classes at application launch (or during the app lifetime). Constructor injection means that you can specify a parameter in a class his constructor. When that class gets instantiated SimpleIoc will try to find a registered class of the same type as the parameter, when it finds one, that instance will get injected as the parameter of the constructor. Here’s an example, let’s say that in the ViewModelLocator, we register a navigation service.

Code Snippet
  1. SimpleIoc.Default.Register<INavigationService, NavigationService>();

We state here that we want to register an INavigationService in the IOC container, when it creates the instance we want it to be of type NavigationService. This “record” in the IOC container doesn’t have an instance yet, it gets instantiated when we fetch it from the container the first time. There are some occasions where you would want to create an instance of a class immediately when it gets registered. the Register<T> function of SimpleIoc has an overload to do just that.

Code Snippet
  1. SimpleIoc.Default.Register<INavigationService, NavigationService>(true);

Just pass in true as a parameter and it will create an instance right there and then.

Now we want to use the NavigationService in the MainViewModel.

Code Snippet
  1. ///<summary>
  2. /// Initializes a new instance of the MainViewModel class.
  3. ///</summary>
  4. public MainViewModel(INavigationService navigationService)
  5. {
  6.     
  7. }

SimpleIoc will search for a registered class of type INavigationService and will inject it in this constructor. This saves us the hassle of manually contacting the IOC container and requesting the correct instance.

WARNING: do be careful with this, the order in which you register your classes with the IOC container can be important, especially when using the overload to create instances. If I would create the MainViewModel before the NavigationService is registered I would get a nullreference exception. So be aware of that.

3. SimpleIoc to simple? replace it!

The SimpleIoc library works great and is a cool, lightweight addition to MVVM Light, but it is actually really lightweight. It is a very realistic scenario that for larger apps the SimpleIoc just won’t do (or you’re like me and want to try out how hard it is to replace it with another one). In this example I’m going to replace SimpleIoc with AutoFac, another well known and very powerful IOC service.

First of all, we’re going to need the AutoFac libraries and the extra library that allows us to use the ServiceLocator, just like SimpleIoc does. So either from the package manager console or from the UI, add the CommonServiceLocator extra for AutoFac, the AutoFac libraries are a dependency so they’ll get installed as well. I’m using a brand new Windows Phone 8 project for this, started from the MVVM Light project template.

Code Snippet
  1. Install-Package Autofac.Extras.CommonServiceLocator

The only place we’ll need to change some code is in the ViewModelLocator.

This is the new ViewModelLocator constructor, I’ve put the old SimpleIoc code in comments so it’s easy to compare

Code Snippet
  1. static ViewModelLocator()
  2. {
  3.     var container = newContainerBuilder();
  4.  
  5.     //ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
  6.     ServiceLocator.SetLocatorProvider(() => newAutofacServiceLocator(container.Build()));
  7.  
  8.     if (ViewModelBase.IsInDesignModeStatic)
  9.     {
  10.         //SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
  11.         container.RegisterType<Design.DesignDataService>().As<IDataService>();
  12.     }
  13.     else
  14.     {
  15.         //SimpleIoc.Default.Register<IDataService, DataService>();
  16.         container.RegisterType<DataService>().As<IDataService>();
  17.     }
  18.  
  19.     //SimpleIoc.Default.Register<MainViewModel>();
  20.     container.RegisterType<MainViewModel>();
  21. }

And that’s it, we declare a ContainerBuilder, set it as the LocatorProvider. The container is then used to register everything we need. The SimpleIoc overload that creates an instance upon registering would look something like this in AutoFac.

Code Snippet
  1. container.RegisterInstance(newDataService()).As<IDataService>();

That’s it, constructor injection should still work exactly like before with SimpleIoc.

4. Built-in messages

MVVM Light has something called the messenger, it registers classes as listeners and can send messages to them. This is commonly used to do communication between viewmodels. Generally I would create a message class for each type of message that I want to send, but MVVM Light has some build in messages that we can use.

GenericMessage<T>(T content) A message that can contain whatever of type T.

Code Snippet
  1. Messenger.Default.Send(newGenericMessage<string>("my message"));
NotificationMessage(string notification)a message that contains a notification. this might be
used to send a notification to a notification factory that will show the message in the preferred way.
Code Snippet
  1. try
  2. {
  3.     //try something
  4. }
  5. catch (Exception ex)
  6. {
  7.     Messenger.Default.Send(newNotificationMessage(ex.Message));
  8. }

There’s also a NotificationMessage<T>(T notification) should you need it.

The next one is NotificationMessageAction(string notification, Action callback) basically the same as the NotificationMessage but you can add a callback action that will fire once the message is received. This one also has the generic implementation just like NotificationMessage.

DialogMessage(string content, Action<MessageBoxResult> callback) 
This message is meant to ask the user to input something and it will return the result of that input in the
MessageBoxResult. MessageBoxResult is an enum that lives in System.Windows
Code Snippet
  1. publicenumMessageBoxResult
  2. {
  3.   None = 0,
  4.   OK = 1,
  5.   Cancel = 2,
  6.   Yes = 6,
  7.   No = 7,
  8. }

 

Code Snippet
  1. Messenger.Default.Send(newDialogMessage("Are you sure?", result =>
  2.     {
  3.         if (result == MessageBoxResult.Yes)
  4.         {
  5.             //do something
  6.         }
  7.     }));

The DialogMessage class inherits from GenericMessage<string>

PropertyChangedMessage(T oldValue, T newValue, string propertyName)
The PropertyChangedMessage is meant to use like the RaisePropertyChanged implementation. This is great when multiple 
viewmodels need to respond to a changed property.
Code Snippet
  1. publicstring WelcomeTitle
  2. {
  3.     get
  4.     {
  5.         return _welcomeTitle;
  6.     }
  7.  
  8.     set
  9.     {
  10.         if (_welcomeTitle == value)
  11.         {
  12.             return;
  13.         }
  14.  
  15.         Messenger.Default.Send(newPropertyChangedMessage<string>(_welcomeTitle, value, "WelcomeTitle"));
  16.  
  17.         _welcomeTitle = value;
  18.         RaisePropertyChanged(WelcomeTitlePropertyName);
  19.     }
  20. }

Be careful when registering listeners, try to use as many different types of messages as makes sense. You don’t want a wrong listener to receive a message because it happens to listen to the same type of message. To register a listener do this:

Code Snippet
  1. Messenger.Default.Register<PropertyChangedMessage<string>>(this, message =>
  2.     {
  3.         var a = message.NewValue;
  4.         //do something
  5.     } );

5. Portable libraries

MVVM Light is available on every XAML based platform. And it comes with a portable version now. The portable version is a separate library on NuGet.

Code Snippet
  1. Install-Package Portable.MvvmLightLibs

If you decide to use the portable version, make sure that every project in your solution that needs the MVVM Light libraries references the portable version. It does not work together with the “normal” MVVM Light libraries. When you use the PCL version, you can put your viewmodels in a separate, portable library and share them over, for example, a Windows Store and a Windows Phone app.

6. Event to Command behavior

MVVM Light has an ICommand implementation called RelayCommand that can be used to bind commands to actions. Like for example a button in XAML has a Command property that can be bound to an ICommand on its datacontext, so that when the button is clicked the ICommand will fire. Unfortunately not every XAML UI element has a bindable command property for every event that they can trigger and that’s where EventToCommand comes into play. With EventToCommand you can bind any event from a XAML UI element to an ICommand in the viewmodel.

First we’ll need two namespaces in our XAML page

Code Snippet
  1. xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  2. xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"

Let’s say that we want to use the Tap event on a stackpanel.

Code Snippet
  1. <StackPanel Grid.Row="0" Orientation="Horizontal">
  2.     <i:Interaction.Triggers>
  3.         <i:EventTrigger EventName="Tap">
  4.             <command:EventToCommand Command="{Binding GoToCommand}" CommandParameter="Edit" />
  5.         </i:EventTrigger>
  6.     </i:Interaction.Triggers>

Line 3 specifies the event that we want to handle, note that this is a string so be aware of typos. Line 4 binds the actual command and can even pass a parameter to the ICommand implementation.

Code Snippet
  1. privateRelayCommand<string> _goToCommand;
  2. publicRelayCommand<string> GoToCommand
  3. {
  4.     get { return _goToCommand jQuery15206875578026641675_1366095632942 (_goToCommand = newRelayCommand<string>(NavigateAway)); }
  5. }

The NavigateAway method has this signature

Code Snippet
  1. privatevoid NavigateAway(string parameter)

The parameter will be the word “Edit” in this case as that’s what we’ve specified in the XAML. We can even pass the eventargs from the event to the Command by changing line 4 from the XAML snippet to this

Code Snippet
  1. <command:EventToCommand PassEventArgsToCommand="True" Command="{Binding GoToCommand}" />

Windows Store applications don’t have these behaviors out of the box so you won’t be able to use EventToCommand there unless you install the Win8nl toolkit from NuGet. Joost Van Schaik has build his own implementation of behaviors in WinRT and thanks to his efforts (and of some other people that have helped in the project) we can now use EventToCommand in WinRT.

7. DispatcherHelper

Since .net 4.5 we have the await/async keywords and being the good little citizens that we are we do a lot of stuff async now. That means if we want to update something that lives on the UI thread we’ll need the Dispatcher class to marshall our action to that thread. Normally we don’t have access to the Dispatcher from our viewmodel classes. MVVM Light contains a DispatcherHelper that will execute an action on the UI thread when needed.

Code Snippet
  1. DispatcherHelper.CheckBeginInvokeOnUI(() =>
  2.     {
  3.         //do something
  4.     });

The DispatcherHelper gets initialized in the App.xaml.cs in the InitializePhoneApplication method (in a WP8 project that is).

DispatcherHelper also has a RunAsync method. The difference with the CheckBeginInvokeOnUI is that the CheckBeginInvokeOnUI will first check if it’s already on the UI thread, if it is it will just execute the action, if it isn’t it will call the RunAsync method.

8. Blendable

MVVM Light has complete Blend support, meaning you can drag and drop properties from the viewmodel onto the view to generate a binding, or you can generate design time data based on the datacontext and so on. I’m really not that good in Blend so I’m not going into detail about this one, just remember that MVVM Light was build with Blend in mind.

9. Open Source

This one you probably knew but MVVM Light is completely open source. http://mvvmlight.codeplex.com/ is the place to be if you want to dive into the source code.

10. Laurent is on Twitter and he’s a nice guy Glimlach

Laurent Bugnion, the founder of MVVM Light, is on Twitter! https://twitter.com/LBugnion he’s a great guy to chat with and very eager to help out anyone who needs help.

 

Conclusion

MVVM Light is a great library with a few hidden gems. In this article I’ve discussed 8 very interesting ones that can make your life as a developer easier. I’ve included two more extra items because 10 is a prettier number than 8 Glimlach

 

 


Tags:

.Net | MVVM Light | Windows 8 | WinRT | WP7 | WP8 | XAML

SQLite with a bit of MVVM Light in Windows Phone 8

by Nico

While SQLce is still a viable solution in Windows Phone 8 to have some form of local database we also have an official SQLite implementation available. So why use SQLite when we can just keep using SQLce? Because Windows 8 only support SQLite and if you ever want to port over your app it would be nice not to have two versions of local databases to maintain. In this post I’ll explain how to implement a SQLite database into an MVVM Light Windows Phone 8 project (there is an unofficial Windows Phone 7 SQLite version as well but I have no idea how stable / buggy that is). I’ll be using Tim Heuer’s SQLite .net wrapper so we can use LINQ to SQLite instead of writing SQL queries manually (hooray for intellisense Smile). Let’s kick things off by creating an empty Windows Phone 8 app.

SQLite

Before we can use SQLite, we’ll need to install the SDK. Click here (official SQLite download page) to download the VSIX file and install it into Visual Studio.

NuGet fun

Before we can write any code we’ll need some NuGet packages. Use these commands in the Package Manager Console.

Install-Package MvvmLight

Install-Package sqlite-net

Install-Package WPtoolkit

Install-Package Cimbalino.Phone.Toolkit

Changing target platform

SQLite is a C++ library, meaning that it should be compiled against the architecture that the app will be running on. On Windows 8 that means creating separate packages for ARM and x86. On Windows Phone 8 that means switching from Any CPU to ARM when running on a device or when creating your XAP. When you’re running your app on the emulator the target platform needs to be set to x86.

Moving files around

When you  install the MVVM Light package it will add some folder structure and some files. I like to adjust this a bit more by adding a View folder and moving the MainPage into that view. That means that the startup page has to change as well. Open up the WMAppManifest.xml and change it like on the screenshot.

At this stage I couldn’t build the project because of a whole bunch of compile errors in the sqlite-net files. If you get the same problem (by the time you read this, it might be fixed), download the sqlite-net source from GitHub and from your project, add a reference to your local sqlite-net repo/lib/wp7/Community.CsharpSqlite.WinPhone.dll and that should fix it right up. Also, add a folder “Model” to the project so that our MVVM folder structure is complete.

The demo app

The app that we’ll be creating today is an app to keep track of tasks, which seems to be the new “Hello, World!”. We’ll start with the model, and work our way up to the view from there. Our class is called “Task” that means we’ll have to be careful that we use Model.Task instead of System.Threading.Task but we’ll manage.

Code Snippet
  1. [Table("Tasks")]
  2. public class Task : INotifyPropertyChanged
  3. {
  4.     private int _id;
  5.     private string _title;
  6.     private DateTime _date;
  7.  
  8.     [PrimaryKey, AutoIncrement]
  9.     public int Id
  10.     {
  11.         get { return _id; }
  12.         set
  13.         {
  14.             if (value == _id) return;
  15.             _id = value;
  16.             OnPropertyChanged("Id");
  17.         }
  18.     }
  19.  
  20.     public string Title
  21.     {
  22.         get { return _title; }
  23.         set
  24.         {
  25.             if (value == _title) return;
  26.             _title = value;
  27.             OnPropertyChanged("Title");
  28.         }
  29.     }
  30.  
  31.     public DateTime Date
  32.     {
  33.         get { return _date; }
  34.         set
  35.         {
  36.             if (value.Equals(_date)) return;
  37.             _date = value;
  38.             OnPropertyChanged("Date");
  39.         }
  40.     }
  41.  
  42.     public event PropertyChangedEventHandler PropertyChanged;
  43.     protected virtual void OnPropertyChanged(string propertyName = null)
  44.     {
  45.         PropertyChangedEventHandler handler = PropertyChanged;
  46.         if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  47.     }
  48. }

The “Task” class implements INotifyPropertyChanged so that controls that are bound to its properties get updated like good citizens. Now for the annotations, those come from sqlite-net and mark this class as a table in the database. The same goes for the annotations on the Id property, that property is marked as being the primarykey and being an autoincremented value. If you have a property that you don’t want in the database, add the [Ignore] attribute and there won’t be any column generated for it. Now that we have a model we can start working on the service, the class that will do all the SQLite communication. (Yes we could do all this in the viewmodel but it’s called seperation of concerns Smile). And to do this the right way we’ll start by creating an interface for the service.

Code Snippet
  1. public interface IDataService
  2. {
  3.     Task SaveTask(Model.Task newTask);
  4.     Task<IList<Model.Task>> LoadTasks();
  5.     Task UpdateTask(Model.Task selectedTask);
  6.     Task DeleteTask(Model.Task selectedTask);
  7. }

Those are all the basic CRUD (Create, Read, Update, Delete) that we can (should be able to) perform on any datacontainer. Here’s the implementation

Code Snippet
  1. public class DataService : IDataService
  2. {
  3.     public async Task SaveTask(Model.Task newTask)
  4.     {
  5.         await App.Connection.InsertAsync(newTask);
  6.     }
  7.  
  8.     public async Task<IList<Model.Task>> LoadTasks()
  9.     {
  10.         return await App.Connection.Table<Model.Task>().ToListAsync();
  11.     }
  12.  
  13.     public async Task UpdateTask(Model.Task selectedTask)
  14.     {
  15.         await App.Connection.UpdateAsync(selectedTask);
  16.     }
  17.  
  18.     public async Task DeleteTask(Model.Task selectedTask)
  19.     {
  20.         await App.Connection.DeleteAsync(selectedTask);
  21.     }
  22.  
  23.     public async Task<IList<SubTask>> LoadSubTasks()
  24.     {
  25.         return await App.Connection.Table<SubTask>().ToListAsync();
  26.     }
  27. }

Hmm looks like I forgot to mention something, go to App.xaml.cs and add this property

Code Snippet
  1. public static SQLiteAsyncConnection Connection { get; set; }

Keep App.xaml.cs open, we’ll need it in a minute. In the DataService class we’re calling all the CRUD methods provided to us by sqlite-net. We can get a list of all records in a table by calling .Table<T>().ToListAsync() or do any of the other CRUD operations by just calling the function and passing in the modified POCO. Really easy and quite powerful.

Let’s jump back to App.xaml.cs, there should be an empty function called Application_Launching. In this function we’ll need to check if the database exists, open a connection to it if it exists or create it first and then open the connection.

Code Snippet
  1. private async void Application_Launching(object sender, LaunchingEventArgs e)
  2. {
  3.     try
  4.     {
  5.         await ApplicationData.Current.LocalFolder.GetFileAsync("taskDB.db");
  6.         Connection = new SQLiteAsyncConnection("taskDB.db");
  7.     }
  8.     catch (FileNotFoundException)
  9.     {
  10.         CreateDB();
  11.     }
  12. }

Unfortunately, there is no DataBaseExists() function like in SQLce so I choose to do it the quick and dirty way. I try to get the database, which is basically a file in the ApplicationData, if the file doesn’t exist it will throw a FileNotFoundException and that’s where I call the CreateDB() method.

Code Snippet
  1. private async void CreateDB()
  2. {
  3.     Connection = new SQLiteAsyncConnection("taskDB.db");
  4.  
  5.     await Connection.CreateTableAsync<Task>();
  6. }

Line 3 creates the database while line 5 creates the Task table in the database. When all that’s in place, we’re ready to move to the viewmodels.

ViewModel

Not much to say here, we all know what a viewmodel is, so here is the MainViewModel.

Code Snippet
  1. public class MainViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     /// <summary>
  7.     /// The <see cref="Tasks" /> property's name.
  8.     /// </summary>
  9.     public const string TasksPropertyName = "Tasks";
  10.  
  11.     private IList<Task> _tasks;
  12.  
  13.     /// <summary>
  14.     /// Sets and gets the Tasks property.
  15.     /// Changes to that property's value raise the PropertyChanged event.
  16.     /// </summary>
  17.     public IList<Task> Tasks
  18.     {
  19.         get
  20.         {
  21.             return _tasks;
  22.         }
  23.  
  24.         set
  25.         {
  26.             if (Equals(_tasks, value))
  27.             {
  28.                 return;
  29.             }
  30.  
  31.             RaisePropertyChanging(TasksPropertyName);
  32.             _tasks = value;
  33.             RaisePropertyChanged(TasksPropertyName);
  34.         }
  35.     }
  36.        
  37.     /// <summary>
  38.     /// The <see cref="NewTask" /> property's name.
  39.     /// </summary>
  40.     public const string NewTaskPropertyName = "NewTask";
  41.  
  42.     private Task _newTask;
  43.  
  44.     /// <summary>
  45.     /// Sets and gets the NewTask property.
  46.     /// Changes to that property's value raise the PropertyChanged event.
  47.     /// </summary>
  48.     public Task NewTask
  49.     {
  50.         get
  51.         {
  52.             return _newTask;
  53.         }
  54.  
  55.         set
  56.         {
  57.             if (_newTask == value)
  58.             {
  59.                 return;
  60.             }
  61.  
  62.             RaisePropertyChanging(NewTaskPropertyName);
  63.             _newTask = value;
  64.             RaisePropertyChanged(NewTaskPropertyName);
  65.         }
  66.     }
  67.  
  68.     public RelayCommand SaveNewTaskCommand
  69.     {
  70.         get { return new RelayCommand(SaveNewTask); }
  71.     }
  72.  
  73.     public RelayCommand<SelectionChangedEventArgs> SelectionChangedCommand
  74.     {
  75.         get { return new RelayCommand<SelectionChangedEventArgs>(SelectionChanged);}
  76.     }
  77.  
  78.     /// <summary>
  79.     /// Initializes a new instance of the MainViewModel class.
  80.     /// </summary>
  81.     public MainViewModel(IDataService dataService, INavigationService navigationService)
  82.     {
  83.         _dataService = dataService;
  84.         _navigationService = navigationService;
  85.         NewTask = new Task { Date = DateTime.Today };
  86.  
  87.         LoadTasks();
  88.     }
  89.  
  90.     private async void LoadTasks()
  91.     {
  92.         Tasks = await _dataService.LoadTasks();
  93.     }
  94.  
  95.     private async void SaveNewTask()
  96.     {
  97.         await _dataService.SaveTask(NewTask);
  98.         Tasks.Add(NewTask);
  99.         NewTask = new Task { Date = DateTime.Today };
  100.     }
  101.  
  102.     private void SelectionChanged(SelectionChangedEventArgs args)
  103.     {
  104.         if (args.AddedItems.Count > 0)
  105.         {
  106.             Messenger.Default.Send(new TaskSelectedMessage(args.AddedItems[0] as Task));
  107.             _navigationService.NavigateTo(new Uri(@"/View/EditPage.xaml", UriKind.Relative));
  108.         }
  109.     }
  110. }

The IDataService field is what we’ve defined just a minute ago, it gets instantiated through the constructor. INavigationService comes from the Cimbalino toolkit, it allows us to do page to page navigation from within the viewmodels. There’s a property of IList<Task> that one will hold all the available tasks, they are loaded at startup, also newly added tasks will be put in that list. There’s a property of type Task, his properties will be bound to the input fields on the new task form, when the user clicks save the property will be pushed to the dataservice to save it in the database. Talking about the save button, there are two RelayCommands (MVVM Light’s implementation of ICommand). One is for saving a new property and the second one is for navigating to the detail page when a task is selected. In the constructor both fields are set and the Task property is initialized, setting the date to today. Since our datepicker will be bound to this property it will automatically be set to today’s date. Loading all the tasks needs to be done asynchronous, since the constructor can’t be marked as async we’ll put the service call in a synchronous method and call that one from the constructor, that way we can use the async / await keywords. Saving a task is as easy as calling the SaveTask function on IDataService and adding the new task to the list, and reinitializing it afterwards to clear all the fields. You might want to think about adding some check here in case something goes wrong while saving to the DB (have it return a boolean for example), I’ll just be living on the edge here and assume this never fails Smile. For navigating to the detail page we’ll add a command to the SelectionChanged event of our LongListSelector. We use the MVVM Light messenger, some sort of implementation of the Observer pattern, to send over the selected item to anyone registered to listen to a message of type TaskSelectedMessage. The TaskSelectedMessage class is pretty basic.

Code Snippet
  1. public class TaskSelectedMessage : MessageBase
  2. {
  3.     public Model.Task Task { get; set; }
  4.  
  5.     public TaskSelectedMessage(Model.Task task)
  6.     {
  7.         Task = task;
  8.     }
  9. }

The class inherits from MessageBase, which is a class in the MVVM Light library, it has one property that is set in the constructor (that’s just to make life a bit easier).

In the MainViewModel, when the SelectionChanged event fires we send a message of this type containing the selected item, once the message is on its way we use the INavigationService to navigate to the detail page.

Here’s the  viewmodel for the editpage.

Code Snippet
  1. public class EditViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     /// <summary>
  7.     /// The <see cref="SelectedTask" /> property's name.
  8.     /// </summary>
  9.     public const string SelectedTaskPropertyName = "SelectedTask";
  10.  
  11.     private Task _selectedTask;
  12.  
  13.     /// <summary>
  14.     /// Sets and gets the SelectedTask property.
  15.     /// Changes to that property's value raise the PropertyChanged event.
  16.     /// </summary>
  17.     public Task SelectedTask
  18.     {
  19.         get
  20.         {
  21.             return _selectedTask;
  22.         }
  23.  
  24.         set
  25.         {
  26.             if (_selectedTask == value)
  27.             {
  28.                 return;
  29.             }
  30.  
  31.             RaisePropertyChanging(SelectedTaskPropertyName);
  32.             _selectedTask = value;
  33.             RaisePropertyChanged(SelectedTaskPropertyName);
  34.         }
  35.     }
  36.  
  37.     public RelayCommand UpdateTaskCommand
  38.     {
  39.         get { return new RelayCommand(UpdateTask); }
  40.     }
  41.  
  42.     public RelayCommand DeleteTaskCommand
  43.     {
  44.         get { return new RelayCommand(DeleteTask); }
  45.     }
  46.  
  47.     public EditViewModel(IDataService dataService, INavigationService navigationService)
  48.     {
  49.         _dataService = dataService;
  50.         _navigationService = navigationService;
  51.  
  52.         Messenger.Default.Register<TaskSelectedMessage>(this, msg => SelectedTask = msg.Task);
  53.     }
  54.  
  55.     private void UpdateTask()
  56.     {
  57.         _dataService.UpdateTask(SelectedTask);
  58.     }
  59.  
  60.     private void DeleteTask()
  61.     {
  62.         _dataService.DeleteTask(SelectedTask);
  63.     }
  64. }

The same fields can be found here (I could put them in a base class, would be cleaner but who cares about clean code anyway? – well you should all care!). One property in this viewmodel, to hold the selected task and bind its properties to the view. A few commands for update and delete, they just call their respective functions on the DataService passing in the selected Task. The interesting part here is in the constructor. The fields get set and we register the viewmodel to listen if the messenger has a message of type TaskSelectedMessage, if it does set the task in the message to the property. However, the viewmodel by default gets instantiated when we navigate to the view meaning that the message has left the building before the receiver has registered as a receiver so it won’t arrive. Let’s fix that shall we? When you’ve added the MVVM Light libraries through NuGet (or you used the MVVM Light project templates) there should be a ViewModelLocator class in your ViewModel folder. This class registers your viewmodels in the TinyIoc container. Registering those viewmodels has an overload that, when set to True, creates an instance of each viewmodel at application launch, meaning that the viewmodels register themselves on the messenger before any message can be send. Here are my viewmodel registrations (from the ViewModelLocator constructor).

Code Snippet
  1. SimpleIoc.Default.Register<MainViewModel>();
  2. SimpleIoc.Default.Register<EditViewModel>(true);

MainViewModel won’t get instantiated at registration but EditViewModel will. So that’s a problem solved. Next piece of the puzzle are those constructor parameters in the viewmodels. They get resolved by dependency injection, we register the correct types here in the ViewModelLocator and when the viewmodel constructor is called, the correct instances will get injected automagically.

Code Snippet
  1. if (ViewModelBase.IsInDesignModeStatic)
  2. {
  3.     // Create design time view services and models
  4.     SimpleIoc.Default.Register<IDataService, DesignService>();
  5. }
  6. else
  7. {
  8.     // Create run time view services and models
  9.     SimpleIoc.Default.Register<IDataService, DataService>();
  10.     SimpleIoc.Default.Register<INavigationService, NavigationService>();
  11. }

Take this for example, when we are in design mode (Blend for example) we can load an IDataService implementation that returns dummy data so that we can style our views very easily (code gets executed when running at designtime so even when you’re not using dummy data it’s a good idea to register these types in an if-block to prevent design time errors).

What everything in place, let’s have a look at the xaml and hook everything up. We’ll start with the MainPage.xaml and since XAML has a tendency of growing quite large, I’ll chop it in pieces. First thing a page needs in an MVVM scenario is a DataContext, meaning our ViewModel. This can be set from code behind (DataContext = new MainViewModel()) but that would just null out every use of the ViewModelLocator. We’ll set the datacontext from XAML.

Code Snippet
  1. <phone:PhoneApplicationPage x:Class="SqLitePoc.View.MainPage"
  2.                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.                             xmlns:command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
  5.                             xmlns:behaviors="clr-namespace:Cimbalino.Phone.Toolkit.Behaviors;assembly=Cimbalino.Phone.Toolkit"
  6.                             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7.                             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  8.                             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9.                             xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  10.                             xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  11.                             xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
  12.                             DataContext="{Binding Main,
  13.                                                   Source={StaticResource Locator}}"
  14.                             FontFamily="{StaticResource PhoneFontFamilyNormal}"
  15.                             FontSize="{StaticResource PhoneFontSizeNormal}"
  16.                             Foreground="{StaticResource PhoneForegroundBrush}"
  17.                             Orientation="Portrait"
  18.                             SupportedOrientations="Portrait"
  19.                             shell:SystemTray.IsVisible="True"
  20.                             mc:Ignorable="d">

The key here is DataContext="{Binding Main, Source={StaticResource Locator}}" this says to the view that its datacontext is bound to a property called Main and that property lives in a resource called Locator (that resource is defined in App.xaml). Now for the page itself, the page consists of a pivot control with two pivot pages, one for entering new tasks and one for viewing a list of all the tasks that have been created so far.

Code Snippet
  1. <!--  LayoutRoot is the root grid where all page content is placed  -->
  2. <Grid x:Name="LayoutRoot" Background="Transparent">
  3.     <!--  Bindable Appbar buttons  -->
  4.     <i:Interaction.Behaviors>
  5.         <behaviors:ApplicationBarBehavior>
  6.             <behaviors:ApplicationBarIconButton Command="{Binding SaveNewTaskCommand, Mode=OneTime}" IconUri="/Assets/AppBar/save.png" Text="Save Task" />
  7.         </behaviors:ApplicationBarBehavior>
  8.     </i:Interaction.Behaviors>
  9.  
  10.     <Grid.RowDefinitions>
  11.         <RowDefinition Height="Auto" />
  12.         <RowDefinition Height="*" />
  13.     </Grid.RowDefinitions>
  14.     <phone:Pivot Title="SQLite POC" Grid.Row="1">
  15.         <phone:PivotItem x:Name="NewTask" CacheMode="{x:Null}" Header="new task">
  16.             <StackPanel>
  17.                 <TextBlock Text="Title" TextWrapping="Wrap" />
  18.                 <TextBox x:Name="TextBoxTitle"
  19.                             Height="72"
  20.                             Text="{Binding NewTask.Title, Mode=TwoWay}"
  21.                             TextWrapping="Wrap" />
  22.                 <TextBlock Text="Complete by" TextWrapping="Wrap" />
  23.                 <toolkit:DatePicker Value="{Binding NewTask.Date, Mode=TwoWay}" />
  24.             </StackPanel>
  25.         </phone:PivotItem>
  26.         <phone:PivotItem x:Name="AllTasks" CacheMode="{x:Null}" Header="all tasks">
  27.             <phone:LongListSelector ItemTemplate="{StaticResource TaskListItemTemplate}" ItemsSource="{Binding Tasks}">
  28.                 <i:Interaction.Triggers>
  29.                     <i:EventTrigger EventName="SelectionChanged">
  30.                         <command:EventToCommand Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True" />
  31.                     </i:EventTrigger>
  32.                 </i:Interaction.Triggers>
  33.             </phone:LongListSelector>
  34.         </phone:PivotItem>
  35.     </phone:Pivot>
  36. </Grid>

First thing in this snippet is a behavior for a bindable appbar button. The default appbar is not bindable, meaning that you can’t bind the buttons Command property to an ICommand on your viewmodel. This wasn’t the case in WP7 and it still isn’t in WP8, bit of a pain. Luckily, Cimbalino toolkit gives us an ApplicationBarBehavior, allowing us to bind our ICommands to the appbar, the only trade off we need to make is that the appbar buttons won’t be visible at design time but that’s a small trade-off in my opinion. We’ll add one button in the appbar, bind it to the SaveNewTaskCommand RelayCommand in MainViewModel and appoint it the save icon. Then there’s the pivot control, first pivotitem contains a stackpanel with a textbox for entering a task title and a datepicker (courtesy of the Windows Phone Toolkit) both are bound to properties of the NewTask property on the MainViewModel. Don’t forget to set the bind mode to TwoWay so that we can update the properties from our view. The second pivot item contains a list of all the tasks. Now, in WP8 they advice us to use the LongListSelector instead of the listbox that’s all great but at least make it behave more like a listbox and not some crippled dependency property missing piece of ****. The problem lies in the SelectedItem property, myself and many other XAML devs usually create a SelectedTask property and bind it to the SelectedItem property of the ListBox, the setter of that SelectedTask property would then be used to navigate to the detailspage. That was a clean, fast solution but the LongListSelector’s SelectedItem property is not a dependency property, meaning it cannot be bound so that’s not a viable solution anymore. Second option would be to bind an ICommand to the SelectionChanged event, again a no-go. There are some implementations of the LongListSelector floating around on the internet that has a bindable SelectedItem property so that would be a solution, another one is to add an EventToCommand behavior and binding the SelectionChanged event to the MainViewModel in the behavior (that’s right Windows 8 devs, we Windows Phone devs still get behaviors out of the box). I’m going with the EventToCommand solution, only thing I haven’t solved here is that when we navigate to the detail page, navigate back to the mainpage and click the same task again it won’t do anything anymore since that item still is the selected item so the selection doesn’t change and the event doesn’t fire. A solution here would be to use the messenger to send a message to the code behind of the view to set the SelectedItem property of the LongListSelector to null.

tl;dr version: LongListSelector kind off sucks but it can be solved.

The LongListSelector is bound to the Tasks collection, the ItemTemplate is defined in the resources part of the page

Code Snippet
  1. <phone:PhoneApplicationPage.Resources>
  2.     <DataTemplate x:Key="TaskListItemTemplate">
  3.         <StackPanel>
  4.             <TextBlock x:Name="Title"
  5.                        Style="{StaticResource JumpListAlphabetStyle}"
  6.                        Text="{Binding Title}"
  7.                        TextWrapping="Wrap" />
  8.             <TextBlock x:Name="Date"
  9.                        Margin="12,0,0,0"
  10.                        Text="{Binding Date}"
  11.                        TextWrapping="Wrap">
  12.                 <Run />
  13.                 <LineBreak />
  14.                 <Run />
  15.             </TextBlock>
  16.         </StackPanel>
  17.     </DataTemplate>
  18. </phone:PhoneApplicationPage.Resources>

That gives the list a nice look (as far as I can tell that is, I really really suck at designing apps…)

Last part on this page is the appbar itself, the button are defined using the Cimbalino toolkit but we need to actually put an appbar on the page, this sits between the resources and the LayoutRoot grid.

Code Snippet
  1. <!--  Buttons are defined using the behaviors in the Cimbalino toolkit to allow a bindable appbar  -->
  2. <phone:PhoneApplicationPage.ApplicationBar>
  3.     <shell:ApplicationBar IsMenuEnabled="True" IsVisible="True" />
  4. </phone:PhoneApplicationPage.ApplicationBar>

And that’s it for the MainPage, on to the final part of this post, the EditPage.xaml

First, the datacontext

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

Then the appbar buttons, again using Cimbalino (these need to sit in the LayoutRoot grid)

Code Snippet
  1. <!--  Bindable Appbar buttons  -->
  2. <i:Interaction.Behaviors>
  3.     <behaviors:ApplicationBarBehavior>
  4.         <behaviors:ApplicationBarIconButton Command="{Binding UpdateTaskCommand, Mode=OneTime}" IconUri="/Assets/AppBar/save.png" Text="Save Task" />
  5.         <behaviors:ApplicationBarIconButton Command="{Binding DeleteTaskCommand, Mode=OneTime}" IconUri="/Toolkit.Content/ApplicationBar.Delete.png" Text="Save Task" />
  6.     </behaviors:ApplicationBarBehavior>
  7. </i:Interaction.Behaviors>

And then there’s the controls

Code Snippet
  1. <!--  TitlePanel contains the name of the application and page title  -->
  2. <StackPanel Grid.Row="0" Margin="12,17,0,28">
  3.     <TextBlock Style="{StaticResource PhoneTextNormalStyle}" Text="SQLite POC" />
  4.     <TextBlock Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" Text="Edit Task" />
  5. </StackPanel>
  6.  
  7. <!--  ContentPanel - place additional content here  -->
  8. <Grid x:Name="ContentPanel"
  9.       Grid.Row="1"
  10.       Margin="12,0,12,0">
  11.     <StackPanel Margin="0,0,0,76">
  12.         <TextBlock Text="Title" TextWrapping="Wrap" />
  13.         <TextBox x:Name="TextBoxTitle" Height="72" Text="{Binding SelectedTask.Title, Mode=TwoWay}" TextWrapping="Wrap" />
  14.         <TextBlock Text="Complete by" TextWrapping="Wrap" />
  15.         <toolkit:DatePicker Value="{Binding SelectedTask.Date, Mode=TwoWay}" />
  16.     </StackPanel>
  17. </Grid>

That’s all pretty much the same as in the MainPage. And with that our small SQLite POC is finished.

Conclusion

In this post I’ve discussed SQLite in a Windows Phone 8 app. What you should take away from this is that as of Windows Phone 8 SQLite is a first class citizen, even more so when using the excellent sqlite-net library. Don’t forget to switch the platform when running on emulator or on a device, this is necessary because SQLite is a C++ library. I’ve also talked a bit about MVVM Light and the way I use it, I don’t claim that this is the best / only way to use the excellent MVVM implementation by Laurent Bugnion but it is one I feel comfortable with and that gives me great results. If you have any questions / remarks, feel free to drop a comment!

 

UPDATE:

for the LongListSelector, you can also use an extension of the control instead of defining a trigger, see http://stackoverflow.com/questions/14586521/bind-viewmodel-to-item-from-longlistselector-in-datatemplate/14600157#14600157 for more detail.
thanks for the tip Glenn (link to Glenn’s Twitter)!


Tags:

.Net | Binding | MVVM Light | Metro | Patterns | WP8 | WP7 | XAML

  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