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

WP8 as bluetooth Start button

by Nico

If you’ve ever used applications like the Office Remote that seem to take over your computer you’ll know that it can provide quite the “magic” experience. As with all magic technologies this one is quite simple as well. All we need is a computer with Bluetooth that runs a small app with a Bluetooth listener and a Windows Phone app that connects to that listener app via Bluetooth. For this demo app I’m going to make the Windows Phone app act like the Start button on a Windows machine.

Simulating the Windows key

The listener application is a small WPF app that has only one button. That button will act like the Start button. To interact with the operating system and simulate a keyboard press we’ll need to import user32.dll and hook into its keybd_event. We’ll want to send ctrl + esc to Windows (acts the same as the Windows key)

Code Snippet
  1. //source: http://www.codeproject.com/Questions/46731/Open-Start-Menu
  2. private static void ShowStartMenu()
  3. {
  4.     // key down event:
  5.     const byte keyControl = 0x11;
  6.     const byte keyEscape = 0x1B;
  7.     keybd_event(keyControl, 0, 0, UIntPtr.Zero);
  8.     keybd_event(keyEscape, 0, 0, UIntPtr.Zero);
  9.  
  10.     // key up event:
  11.     const uint keyeventfKeyup = 0x02;
  12.     keybd_event(keyControl, 0, keyeventfKeyup, UIntPtr.Zero);
  13.     keybd_event(keyEscape, 0, keyeventfKeyup, UIntPtr.Zero);
  14. }
  15.  
  16. [DllImport("user32.dll")]
  17. static extern void keybd_event(byte bVk, byte bScan, uint dwFlags,
  18.    UIntPtr dwExtraInfo);

In the event handler of the button we call ShowStartMenu() and behold: a wild software Windows key appears!

Building the Bluetooth listener

Adding Bluetooth support to a .NET application isn’t the easiest thing to do. Luckily for us there are libraries out there that take out the hassle. For this project I used Peter Foot’s 32feet.NET library available through NuGet

Install-Package 32feet.NET

A small note on this package as found on the 32feet.NET product page

“Bluetooth support requires a device with the Microsoft or Widcomm Bluetooth stack”

Luckily for me, my device uses the Microsoft BT stack, so I’m good to go. Now on to the code, we’ll need to start a BT listener and once connected read data from a networkstream. If we receive a certain message we’ll execute the ShowStartMenu() method.

First some fields

Code Snippet
  1. private BluetoothListener _listener;
  2.  
  3. //unique service identifier
  4. private readonly Guid _service = new Guid("{7A51FDC2-FDDF-4c9b-AFFC-98BCD91BF93B}");
  5. private bool _connected;

BluetoothListener is a class we get from 32feet.NET. The GUID is a reference to the service this app is providing, our Windows Phone app will need the same GUID to be able to connect to this service. And the third field is a boolean to keep track of having a connected client or not.

Code Snippet
  1. private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
  2. {
  3.     BluetoothRadio br = BluetoothRadio.PrimaryRadio;
  4.  
  5.     if (br == null)
  6.     {
  7.         MessageBox.Show("No supported Bluetooth radio/stack found.");
  8.     }
  9.     else if (br.Mode != RadioMode.Discoverable)
  10.     {
  11.         MessageBoxResult rslt = MessageBox.Show("Make BluetoothRadio Discoverable?",
  12.             "Bluetooth Remote Listener", MessageBoxButton.YesNo);
  13.  
  14.         if (rslt == MessageBoxResult.Yes)
  15.         {
  16.             br.Mode = RadioMode.Discoverable;
  17.         }
  18.     }
  19.  
  20.     _listener = new BluetoothListener(_service);
  21.     _listener.Start();
  22.  
  23.     System.Threading.Thread t = new System.Threading.Thread(ListenLoop);
  24.     t.Start();
  25. }

In the OnLoaded event from the MainWindow we’ll first check if there’s a BT radio found that works on the MS or Widcomm stack. If that’s found, and made discoverable, we’ll start the listener with the service GUID specified in the field. Once the listener is started we fire up a second thread that will contain a loop to connect a client and read data from the stream.

Code Snippet
  1. private void ListenLoop()
  2. {
  3.     byte[] buffer = new byte[1024];
  4.  
  5.     while (true)
  6.     {
  7.         BluetoothClient bc;
  8.         Stream ns;
  9.  
  10.         try
  11.         {
  12.             bc = _listener.AcceptBluetoothClient();
  13.             ns = bc.GetStream();
  14.             _connected = true;
  15.         }
  16.         catch
  17.         {
  18.             break;
  19.         }
  20.  
  21.         //keep connection open
  22.         while (_connected)
  23.         {
  24.             try
  25.             {
  26.                 int received = ns.Read(buffer, 0, buffer.Length);
  27.  
  28.                 if (received > 0)
  29.                 {
  30.                     string data = Encoding.UTF8.GetString(buffer);
  31.  
  32.                     string command = data.Substring(0, data.IndexOf("\0", StringComparison.Ordinal));
  33.  
  34.                     if (command == "Start")
  35.                     {
  36.                         ShowStartMenu();
  37.                     }
  38.                 }
  39.                 else
  40.                 {
  41.                     //connection lost
  42.                     _connected = false;
  43.                 }
  44.             }
  45.             catch
  46.             {
  47.                 _connected = false;
  48.                 break;
  49.             }
  50.         }
  51.  
  52.         try
  53.         {
  54.             bc.Close();
  55.         }
  56.         catch
  57.         {
  58.         }
  59.     }
  60. }

This is the code for the loop that runs in the second thread. First we declare a buffer of 1KB, more than enough for this sample. Next we start an infinite loop, in that loop we declare a BluetoothClient and a Stream. Once a client connects through the AcceptBluetoothClient method we fetch a stream and set the connected flag to true. As long as we’re connected we read data from the stream into the buffer, once we receive actual data we’ll decode it from a byte array (the buffer) into a string (the original message). In this sample the message will be 5 bytes but the buffer can hold 1024 bytes. It will fill up the remaining bytes with “\0” so we’ll need to chop that of with a Substring. If the received string is “Start” we’ll flip to the Start screen. If we read from the stream but the number of received bytes is zero, we’ve lost the connection to the client.

Fire up the WPF app, make sure the button flips you to the Start screen and let’s get started on the WP8 app!

Windows Phone Client

The Windows Phone app consists of two pages. The MainPage is for selecting a Bluetooth peer to connect to and the ConnectedPage has the same button as the WPF application. The app uses MVVM Light, everything happens in the MainViewModel. Both the MainPage and ConnectedPage use MainViewModel as their datacontext. For navigation I’ve added the always helpful Cimbalino NuGet package and registered their NavigationService in SimpleIoc through the ViewModelLocator

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.     }
  9.     else
  10.     {
  11.         // Create run time view services and models
  12.         SimpleIoc.Default.Register<INavigationService, NavigationService>();
  13.     }
  14.  
  15.     SimpleIoc.Default.Register<MainViewModel>();
  16. }

In the MainViewModel I have declared three properties

Code Snippet
  1. private ObservableCollection<PeerInformation> _peers;
  2. private PeerInformation _selectedPeer;
  3. private ICommand _goToStartCommand;
  4.  
  5. public ICommand GoToStartCommand
  6. {
  7.     get { return _goToStartCommand ?? (_goToStartCommand = new RelayCommand(SendCommand)); }
  8. }
  9.  
  10. public ObservableCollection<PeerInformation> Peers
  11. {
  12.     get { return _peers; }
  13.     set
  14.     {
  15.         if (_peers == value) return;
  16.  
  17.         _peers = value;
  18.         RaisePropertyChanged(() => Peers);
  19.     }
  20. }
  21.  
  22. public PeerInformation SelectedPeer
  23. {
  24.     get { return _selectedPeer; }
  25.     set
  26.     {
  27.         if (_selectedPeer == value) return;
  28.  
  29.         _selectedPeer = value;
  30.         RaisePropertyChanged(() => SelectedPeer);
  31.  
  32.         ConnectToDevice();
  33.     }
  34. }

The PeerInformation class is something we get from the Windows Phone Bluetooth API. We have an observablecollection that will hold all peers that are known for your Windows Phone device, we also have a property for the selected peer and a command that will fire a message into the NetworkStream.

We’ll also need some fields

Code Snippet
  1. private StreamSocket _socket;
  2. private DataWriter _dataWriter;
  3.  
  4. private readonly INavigationService _navigationService;

The socket will hold the connection between the phone app and the WPF app. The DataWriter can write data into the stream. The NavigationService is the one from the Cimbalino toolkit.

Here’s the constructor for the MainViewModel

Code Snippet
  1. public MainViewModel(INavigationService navigationService)
  2. {
  3.     if (IsInDesignModeStatic) return;
  4.  
  5.     _navigationService = navigationService;
  6.  
  7.     if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Emulator)
  8.     {
  9.         MessageBox.Show("Bluetooth not available in the emulator");
  10.     }
  11.     else
  12.     {
  13.         RefreshPairedDevicesList();
  14.     }
  15. }

The NavigationService is injected via SimpleIoc. First we check if the current device is the Windows Phone emulator, the emulator doesn’t support Bluetooth so we need an actual device to test this on.

The RefreshPairedDevicesList looks like this (all using the Windows Phone Bluetooth APIs)

Code Snippet
  1. private async void RefreshPairedDevicesList()
  2. {
  3.     try
  4.     {
  5.         // Search for all paired devices
  6.         PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
  7.         var peers = await PeerFinder.FindAllPeersAsync();
  8.  
  9.         Peers = new ObservableCollection<PeerInformation>(peers);
  10.     }
  11.     catch (Exception ex)
  12.     {
  13.         if ((uint)ex.HResult == 0x8007048F)
  14.         {
  15.             if (MessageBox.Show("Bluetooth is off, enable it?",
  16.                 "Bluetooth Off", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
  17.             {
  18.                 ConnectionSettingsTask connectionSettingsTask = new ConnectionSettingsTask
  19.                 {
  20.                     ConnectionSettingsType = ConnectionSettingsType.Bluetooth
  21.                 };
  22.                 connectionSettingsTask.Show();
  23.                 RefreshPairedDevicesList();
  24.             }
  25.         }
  26.         else
  27.         {
  28.             MessageBox.Show(ex.Message);
  29.         }
  30.     }
  31. }

First we’ll look for all paired devices for our phone, those get pushed into the observablecollection. If that fails with result 0x8007048F that means that Bluetooth is disabled on the device, in that case we use the ConnectionSettingsTask to redirect the user to the Bluetooth settings page in WP8.

After the list of peers is build, the user will be able to select one (I’ll discuss the pages in a minute). When a peer is selected we open up the Bluetooth connection

Code Snippet
  1. private async void ConnectToDevice()
  2. {
  3.     if (_socket != null)
  4.     {
  5.         // Disposing the socket with close it and release all resources associated with the socket
  6.         _socket.Dispose();
  7.     }
  8.  
  9.     try
  10.     {
  11.         _socket = new StreamSocket();
  12.  
  13.         //connect to the service with specified GUID
  14.         await _socket.ConnectAsync(SelectedPeer.HostName, "{7A51FDC2-FDDF-4c9b-AFFC-98BCD91BF93B}");
  15.  
  16.         // Connection was successful
  17.         _dataWriter = new DataWriter(_socket.OutputStream);
  18.         _navigationService.NavigateTo("/ConnectedPage.xaml");
  19.     }
  20.     catch (Exception ex)
  21.     {
  22.         MessageBox.Show(ex.Message);
  23.  
  24.         _socket.Dispose();
  25.         _socket = null;
  26.     }
  27. }

The ConnectAsync method takes in the hostname of the peer and the same GUID we used in the WPF application to start the service. Once the connection is made we take the OutputStream and use it to initialize the DataWriter and we navigate to the ConnectedPage.

Let’s have a quick look at the MainPage xaml.

Code Snippet
  1. <phone:LongListSelector ItemsSource="{Binding Peers}">
  2.     <phone:LongListSelector.ItemTemplate>
  3.         <DataTemplate>
  4.             <TextBlock Margin="12, 0, 0, 12"
  5.                        Style="{StaticResource PhoneTextTitle2Style}"
  6.                        Text="{Binding DisplayName}" />
  7.         </DataTemplate>
  8.     </phone:LongListSelector.ItemTemplate>
  9.     <i:Interaction.Behaviors>
  10.         <behaviors:SelectedItemBehavior SelectedItem="{Binding SelectedPeer, Mode=TwoWay}" />
  11.     </i:Interaction.Behaviors>
  12.  
  13. </phone:LongListSelector>

The MainPage consists of a LongListSelector with an ItemsSource bound to the observableCollection on the MainViewModel. as a DataContext we show the displaynames of all available peers.

NOTE: LongListSelector does not support SelectedItem binding. I’ve added a behavior to this project that gives us just that. For more information on the behavior see my blogpost from a while ago.

The ConnectedPage only has a button with a command bound to the GoToStartCommand on MainViewModel. Once that command is fired we send a string “Start” on to the stream.

Code Snippet
  1. private async void SendCommand()
  2. {
  3.     _dataWriter.WriteString("Start");
  4.     await _dataWriter.StoreAsync();
  5.     await _dataWriter.FlushAsync();
  6. }

And that’s it! The message gets written into the DataWriter, stored in the stream and the stream gets flushed. In the WPF app the string gets read into the buffer as a byte array, gets converted back into a string and the Start screen appears!

Wrap-up

In this post I’ve discussed how to connect your Windows Phone device to another bluetooth enabled device and use a service running there.

Happy coding!


Tags:

.Net | Devices | Bluetooth | MVVM Light | WP8 | WPF | XAML | Windows programming

Data validation in Windows Phone 8

by Nico

Whenever you need to do data input you’re probably going to add some form of data validation. There is a ton of information out there on how to do this in Silverlight and WPF but information on Windows Phone 8 is rather hard to find. After doing some research on the topic I’ve landed on the Fluent Validation library available on Nuget and decided to write something on the subject myself. I’ve put together a quick sample, including integration with SimpleIoc in MVVM Light.

Adding the package

We start of with an empty solution, add the MVVM Light libraries to it, bind the datacontext of MainPage to MainViewModel as you would usually do. Once the MVVM setup is complete it’s time to add the Fluent Validation package to the project.

Install-Package FluentValidation

Fluent Validation is an open source project available on Codeplex

Fluent Validation has libraries for

  • .net 4.0
  • MVC 3
  • MVC 4
  • MVC 5
  • Portable

The settings of the portable class library are

Meaning that the implementation I’m about to show will work just as well on Windows Store apps, so +1 for code sharing!

Creating the Model

The demo app is a simple registration form, a new user will be able to enter his name, birthdate and country. We’ll build validation rules on those properties later on. We’ll only have one model class in this app, called Member.

Code Snippet
  1. public class Member
  2. {
  3.     public string Name { get; set; }
  4.     public DateTime BirthDate { get; set; }
  5.     public string Country { get; set; }
  6. }

Setting up the validation

There is some work involved in getting everything setup, don’t worry, it’s hardly rocket science.

We’re going to create a ValidaterFactory. We need this because we’re going to use SimpleIoc to inject the validators into the ViewModels. If you don’t want to do this you can just create the validators and instantiate them whenever you need one, the Codeplex page of Fluent Validation has great documentation on this.

A ValidatorFactory inherits from the ValidatorFactoryBase class included in the library

Code Snippet
  1. public class ValidatorFactory : ValidatorFactoryBase
  2. {
  3.     public ValidatorFactory()
  4.     {
  5.         //register the Validators
  6.         SimpleIoc.Default.Register<IValidator<Member>, MemberValidator>();
  7.     }
  8.  
  9.     public override IValidator CreateInstance(Type validatorType)
  10.     {
  11.         return SimpleIoc.Default.GetInstance(validatorType) as IValidator;
  12.     }
  13. }

The constructor of the ValidatorFactory is where I’m registering all validators. You could do this in the ViewModelLocator as well, like any other class / repository / viewmodel but this keeps my VMLocator cleaner and keeps the validation logic a bit closer together.

The CreateInstance function needs to be overridden and returns the instance of the requested validator.

Building a validator

Almost there, in this step we’re building a validator for the Member class. A validator inherits from AbstractValidator<T> where T is the class you want to validate.

Code Snippet
  1. public class MemberValidator : AbstractValidator<Member>
  2. {
  3.     public MemberValidator()
  4.     {
  5.         RuleFor(member => member.Name).NotEmpty();
  6.         RuleFor(member => member.BirthDate).LessThan(DateTime.Today);
  7.     }
  8. }

In the constructor of the validator we can finally start to add some rules. In this case we’re saying that the Name property should not be empty and that the birthdate property should be before today’s date.

We’ll need to register this class into our IOC, so in ViewModelLocator add this line

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

We pass in ‘true’ as parameter to make sure the object is instantiated at the moment of registration, that way all validators are registered in the IOC as well (as seen in the ValidatorFactory’s constructor).

As a reference, these are all the built in validators of Fluent Validation

  • NotNull
  • NotEmpty
  • NotEqual
  • Equal
  • Length
  • LessThan
  • LessThanOrEqual
  • GreaterThan
  • GreaterThanOrEqual
  • Predicate
  • RegEx
  • Email

Quite an impressive list, and probably most of what you’ll need. Just in case that the one that you need isn’t included, you can build your own, we’ll discuss that in a bit. Let’s get these rules to work first.

Validating data

So we have a factory, we have a validator, all are getting registered in our IOC, time to hook up the ViewModels and getting some validation done.

In the MainViewModel we add a property of type Member that we’ll bind against

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

Next, we’ll add two fields, one for the validator and one for the save command

Code Snippet
  1. private ICommand _saveMemberCommand;
  2. private IValidator<Member> _validator;

Next up is the ICommand property for the Save Command

Code Snippet
  1. public ICommand SaveMemberCommand
  2. {
  3.     get { return _saveMemberCommand ?? (_saveMemberCommand = new RelayCommand(SaveMember)); }
  4. }

Before we dive into the SaveMember method, we’ll need to do some constructor injection and initialization.

Code Snippet
  1. public MainViewModel(ValidatorFactory validator)
  2. {
  3.     NewMember = new Member
  4.     {
  5.         BirthDate = DateTime.Today
  6.     };
  7.  
  8.     _validator = validator.GetValidator<Member>();
  9. }

As a parameter we get our ValidatorFactory, using its GetValidator<T> function we can fill up the _validator field. NewMember gets instantiated and the BirthDate property is set to a default of today.

And last but not least, the SaveMember method

Code Snippet
  1. private void SaveMember()
  2. {
  3.     if (IsValid())
  4.     {
  5.         MessageBox.Show("Registration completed!");
  6.     }
  7. }
  8.  
  9. private bool IsValid()
  10. {
  11.     ValidationResult validationResult = _validator.Validate(NewMember);
  12.  
  13.     if (!validationResult.IsValid)
  14.     {
  15.         ShowErrors(validationResult.Errors);
  16.  
  17.         return false;
  18.     }
  19.  
  20.     return true;
  21. }
  22.  
  23. private void ShowErrors(IEnumerable<ValidationFailure> errors)
  24. {
  25.     StringBuilder builder = new StringBuilder();
  26.  
  27.     builder.AppendLine("The following errors occured:");
  28.     foreach (ValidationFailure error in errors)
  29.     {
  30.         builder.AppendLine("- " + error.ErrorMessage);
  31.     }
  32.  
  33.     MessageBox.Show(builder.ToString(), "error", MessageBoxButton.OK);
  34. }

To validate an instance we call the Validate function on a validator for that type, in this case ‘Member’. That function returns a ValidationResult. ValidationResult contains a bool property IsValid and a list of errors that it found.

We iterate over this list and put every error into a StringBuilder to get a nice error message in a messagebox. If I try to save with an empty name and today’s date as birthdate I get this.

Our validation is working! But those messages could be a bit better. Fluent Validator provides us with options to adjust the property name or the entire message. Change the constructor of the MemberValidator to this

Code Snippet
  1. public MemberValidator()
  2. {
  3.     RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
  4.     RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
  5. }

On line 3 we use .WithMessage(“”) to replace the default message by whatever we want. Line 4 replaces the default name of the property, the result is similar yet slightly different

Adding a custom validator

Let’s say that we want to add validation to the Country property. This property must have a value of either ‘Belgium’, ‘Netherlands’ or ‘Luxemburg’ (this is called the BeNeLux). Obviously, this isn’t included as one simple validator so we’ll just build it ourselves.

We’ll need a class that inherits from PropertyValidator and overrides the IsValid function.

Code Snippet
  1. public class CountryMustBeInBenelux : PropertyValidator
  2. {
  3.     public CountryMustBeInBenelux()
  4.         : base("{PropertyName} is not a Benelux country")
  5.     {
  6.  
  7.     }
  8.  
  9.     protected override bool IsValid(PropertyValidatorContext context)
  10.     {
  11.         if (context.PropertyValue == null)
  12.             return false;
  13.  
  14.         string country = context.PropertyValue.ToString().ToLower();
  15.  
  16.         return country == "belgium" || country == "netherlands" || country == "luxemburg";
  17.     }
  18. }

The string that we pass in to the base constructor is the default message that will be used for this validator. The IsValid function takes a parameter of PropertyValidatorContext. This will contain the property that we want to validate and its value.

Next, in the MemberValidator constructor we add the validation for the Country property

Code Snippet
  1. public MemberValidator()
  2. {
  3.     RuleFor(member => member.Name).NotEmpty().WithMessage("You should enter your name");
  4.     RuleFor(member => member.BirthDate).LessThan(DateTime.Today).WithName("date of birth");
  5.  
  6.     RuleFor(member => member.Country).SetValidator(new CountryMustBeInBenelux());
  7. }

As you can see we need to use the SetValidator function to add our own validator.

The result now is this (I’ve entered a name and a valid birthdate to clean up the error list a bit)

 

Conclusion

In this article I’ve discussed the use of Fluent Validator to do data validation in Windows Phone 8 apps. I’ve used the portable version of the library so these examples should work just fine on Windows 8 as well.

The Fluent Validator library has many more options than what I’ve discussed here and they are all well documented, head over the the Codeplex page if you want to do more and deeper validation.

The sample project can be found on my SkyDrive


Tags:

.Net | Data | Validation | Fluent | MVVM Light | NuGet | WP8 | Windows 8 | WinRT | 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

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

Porting a real win8 app to WP8–part 2

by Nico

Porting a real win8 app to WP8 – part 1

In part one of my adventure I described the architecture of my app and how I managed to move all viewmodels into a PCL (portable class library) but I didn’t use them yet. The main consensus of part one was that I needed to do quite some refactoring and add a lot of abstractions to the project in order to move over viewmodels to PCL projects. In part 2 I’ll describe how I got the viewmodels to work and how I re-enabled page navigation in the Windows 8 version. And with a bit of luck in part 3 I’ll be talking about the Windows Phone 8 version of this app.

A small note on part 1

I wasn’t very happy with part 1 since I needed to create some extra layers and abstractions. Since then the Microsoft Techdays have come and gone and with that two very interesting sessions that made me rethink some stuff. The session were from Laurent Bugnion (his blog, his Twitter) (the creator of the awesome MVVM Light toolkit) and Gill Cleeren (his blog, his Twitter) (a Belgian Silverlight MVP, RD and Win8 enthusiast). From Laurent I learned some tips and tricks concerning the ViewModelLocator class and specifically how to correctly use it in a portable library (more on that in part 3 since I haven’t implemented it yet). Gill gave a session on advanced MVVM tactics and one sentence kept vibrating in my mind “an extra class doesn’t cost a thing” next to that his demo app was filled with layers of abstractions way beyond the extra layers I needed to add to get the project to build again. After that session I felt reassured that I was going down a pretty good path with the revised architecture I had build in part 1. If you want to take a look at that session yourself, the recording of the SilverlightShow version is available here.

About part 2

The last couple of days I found some spare time to mess around with the project again. I’m now at the stage where the Windows Store app is using the portable ViewModels and the navigation is working properly. Those parts are what I’ll discuss here.

Using the ViewModels

Having the portable ViewModels ready it was time to switch to them. I deleted every viewmodel that was still in my client project, except for the ViewModelLocator, that one will be moved later. I registered the new abstraction layers in the ViewModelLocator, making sure that this only happened at runtime, not at designtime and tried to build the app. I couldn’t believe my eyes when I saw the message “Build succeeded”. I replaced the viewmodels in my client project with the ones in the portable library and it still builds! In case you’re interested, this is what’s getting registered in my ViewModelLocator at this time.

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<INavigationService, NavigationService>();
  14.         SimpleIoc.Default.Register<IService, SDKBroker.WinRT.Service>();
  15.         SimpleIoc.Default.Register<IMessageApi, MessageApi>();
  16.         SimpleIoc.Default.Register<IFrameworkApi, FrameworkApi>();
  17.         SimpleIoc.Default.Register<IDispatcher, Dispatcher>();
  18.         SimpleIoc.Default.Register<INetworkApi, NetworkApi>();
  19.     }
  20.  
  21.     //register viewmodels
  22.     SimpleIoc.Default.Register<MainViewModel>();
  23.     SimpleIoc.Default.Register<VolumeDetailViewModel>(true);
  24.     SimpleIoc.Default.Register<CharacterDetailViewModel>(true);
  25.     SimpleIoc.Default.Register<TeamDetailViewModel>(true);
  26.     SimpleIoc.Default.Register<IssueDetailViewModel>(true);
  27.     SimpleIoc.Default.Register<SearchViewModel>();
  28.     SimpleIoc.Default.Register<DetailViewModel>(true);
  29.     SimpleIoc.Default.Register<StoryArcDetailViewModel>(true);
  30.     SimpleIoc.Default.Register<LocationDetailViewModel>(true);
  31.     SimpleIoc.Default.Register<PersonDetailViewModel>(true);
  32.     SimpleIoc.Default.Register<CollectionViewModel>();
  33.     SimpleIoc.Default.Register<NewsFeedViewModel>(true);
  34. }

Everything in the else block gets registered only at runtime. The viewmodels themselves can get registered at designtime just in case I ever want to incorporate designtime test data (something I really should do actually). Notice that some ViewModel registrations get passed a boolean parameter? The Register method of SimpleIoc has an optional parameter stating whether or not the object should get instantiated immediately. Since some viewmodels are listening for messages from the Messenger class in MVVM Light they need their instance right of the bat so they can register as listeners.

I tried to run the app, it started and data was coming in, I could use the button to show the search charm but no navigation was working. That made sense since all navigation commands are now going to ISomePage instead of SomePage and those interfaces weren’t doing anything yet. So I had to make every page implement the correct interface and put together a way to navigate to the correct page from the interface.

Implementing the interface is easy enough (they’re all just empty interfaces). Next problem was that those interfaces are inside of a folder called View in the ViewModel PCL and they need to be known in the Framework.WinRT project (that’s where the NavigationService lives). So I’ve added another PCL called it ComicDB.View and moved all interfaces there. (I couldn’t reference the ViewModel project in the Framework project, it would create a circular dependency). After adding all references everything was building again but still no navigation. To get this to work I changed the Navigate method on the NavigationService from this

Code Snippet
  1. publicvirtualbool Navigate(Type destination, object parameter = null)
  2. {
  3.     try
  4.     {
  5.         _rootFrame.Navigate(destination, parameter);
  6.  
  7.         returntrue;
  8.     }
  9.     catch (Exception e)
  10.     {
  11.         returnfalse;
  12.     }
  13. }

to this

Code Snippet
  1. publicvirtualbool Navigate(Type destination, object parameter = null)
  2. {
  3.     try
  4.     {
  5.         NavigateToPage(destination, parameter);
  6.  
  7.         returntrue;
  8.     }
  9.     catch (Exception e)
  10.     {
  11.         returnfalse;
  12.     }
  13. }
  14.  
  15. privatevoid NavigateToPage(Type destination, object parameter)
  16. {
  17.     try
  18.     {
  19.         //get the implementation for the view
  20.         var instance = SimpleIoc.Default.GetInstance(destination);
  21.         var type = instance.GetType();
  22.  
  23.         _rootFrame.Navigate(type, parameter);
  24.     }
  25.     catch (ActivationException)
  26.     {
  27.         //no registered type found, just navigate to the destination, maybe it's not an interface
  28.         _rootFrame.Navigate(destination, parameter);                                
  29.     }
  30. }

The Navigate method passes everything to the NavigateToPage method that tries to resolve a registered instance of the passed in type, should this fail it throws an ActivationException, in that case just try to navigate. This allows us to navigate to pages that don’t use any interface. Once we get the instance out of the IOC we get its type and pass that into the navigate command of the frame. Obviously, before this starts working we need to register the pages in the IOC and that happens in the ViewModelLocator.

So to finish this part 2 of, here’s the complete constructor of my ViewModelLocator

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<INavigationService, NavigationService>();
  14.         SimpleIoc.Default.Register<IService, SDKBroker.WinRT.Service>();
  15.         SimpleIoc.Default.Register<IMessageApi, MessageApi>();
  16.         SimpleIoc.Default.Register<IFrameworkApi, FrameworkApi>();
  17.         SimpleIoc.Default.Register<IDispatcher, Dispatcher>();
  18.         SimpleIoc.Default.Register<INetworkApi, NetworkApi>();
  19.     }
  20.  
  21.     //register views
  22.     SimpleIoc.Default.Register<IMainPage, MainPage>();
  23.     SimpleIoc.Default.Register<IVolumeDetailPage, VolumeDetailPage>();
  24.     SimpleIoc.Default.Register<ICharacterDetailPage, CharacterDetailPage>();
  25.     SimpleIoc.Default.Register<ICollectionPage, CollectionPage>();
  26.     SimpleIoc.Default.Register<IDetailPage, DetailPage>();
  27.     SimpleIoc.Default.Register<IIssueDetailPage, IssueDetailPage>();
  28.     SimpleIoc.Default.Register<ILocationDetailPage, LocationDetailPage>();
  29.     SimpleIoc.Default.Register<INewsFeedPage, NewsFeedPage>();
  30.     SimpleIoc.Default.Register<IPersonDetailPage, PersonDetailPage>();
  31.     SimpleIoc.Default.Register<IStoryArcDetailPage, StoryArcDetailPage>();
  32.     SimpleIoc.Default.Register<ITeamDetailPage, TeamDetailPage>();
  33.  
  34.     //register viewmodels
  35.     SimpleIoc.Default.Register<MainViewModel>();
  36.     SimpleIoc.Default.Register<VolumeDetailViewModel>(true);
  37.     SimpleIoc.Default.Register<CharacterDetailViewModel>(true);
  38.     SimpleIoc.Default.Register<TeamDetailViewModel>(true);
  39.     SimpleIoc.Default.Register<IssueDetailViewModel>(true);
  40.     SimpleIoc.Default.Register<SearchViewModel>();
  41.     SimpleIoc.Default.Register<DetailViewModel>(true);
  42.     SimpleIoc.Default.Register<StoryArcDetailViewModel>(true);
  43.     SimpleIoc.Default.Register<LocationDetailViewModel>(true);
  44.     SimpleIoc.Default.Register<PersonDetailViewModel>(true);
  45.     SimpleIoc.Default.Register<CollectionViewModel>();
  46.     SimpleIoc.Default.Register<NewsFeedViewModel>(true);
  47. }

It registers all my api and service layers, all my views that have an interface and all viewmodels.

Part 2 conclusion

After a rough start in Part 1 it seems that this experiment has forced me to improve my code by making me add some abstractions. This makes for easier reusable code, both on the same platform as on other platforms. The DEV branch of my app project is once again a fully functional Windows Store app that reacts and behaves exactly as the one that’s in the store right now. The next step is to refactor out the ViewModelLocator and then it should be about time to start work on the Windows Phone version. See you in part 3!


Tags:

.Net | Devices | Metro | MVVM Light | PCL | Windows 8 | WinRT | WP8

Porting a real win8 app to WP8–part 1

by Nico

A few weeks ago the first version of my Windows 8 app (finally) hit the store (download it here).  From the start I wanted to port this application to Windows Phone 8 as well but I didn’t keep that in mind when developing the app. Some time ago, the portable HttpClient was released in a beta version and to me that was the perfect time to see how useful the portable class libraries (PCL) really are.

Most of the information available on the internet on sharing code between Windows Store and Windows Phone apps have those really small basic projects, good stuff to get started, but I want to port an entire, finished project to another platform. Perfect content for some blog posts so I’ll be documenting my progress here on my blog, hopefully it will be to some use.

The app

The app is called Comic Cloud and is a continuation of my very first Windows Phone 7 app ever. It allows users to search for anything related to comic books (volumes, issues, artists, characters, locations, …) and provides a whole bunch of information on the topic. The data comes from a community driven website (think Wikipedia for comics) called ComicVine. They have a great REST API with great documentation so that was perfect. On the other hand, and this is new in the Windows 8 version, users can start tracking their own collection of comic books and keep track of which issues in their collection are already read. This data is saved on Azure by using the awesome Azure Mobile Services, authentication happens with the Microsoft Account (single sign-on). So researching and collection are the two keywords of the application. Since the API is REST based, I make extensive use of the HttpClient class to make the API calls.

Architecture

As for architecture, all libraries are Windows Store class libraries and then off course there’s the app itself, written in C# and XAML. This image shows the projects and their dependencies.

(The app was called ComicDB in its begin stages, the namespaces stayed but the app title was changed to Comic Cloud)

The solution exists of five projects, first there’s the app itself using MVVM Light, win8nl for winRT behaviors (written by Joost van Schaik), MarkedUp for analytics, Callisto for settings fly-out, the Live SDK for the User class and the Telerik RAD controls for their controls (obviously).

The Model project contains all classes, there’s the ComicVine classes (thank God for paste JSON as class…) and some classes for RSS feeds and links.

Since I want to limit the amount of data stored in my WAMS database, I only save the userID and the link to the ComicVine API for each item. For that I needed a second version of some classes, that’s what the DTO project is for.

The framework is a project that I can reuse in other projects without changing anything, all classes that are app independent. Things like the RestClient (providing generic CRUD functions), the GroupInfoList for grouped gridviews, navigationservice to navigate between pages and so on. The ComicVineHelper is an extension method that changes the casing of some object to be compatible with the way the ComicVine API works. All these classes are implementing interfaces, so that will be a big plus when I start porting.

The SDKBroker takes all the different services I use and puts them together in one big SDK that’s easy to use from the app.

The idea

So the idea was to take all those libraries, put them in PCL libraries and reference them from both the Windows Store app and the Windows Phone app. Next to that I wanted to use the portable version of MVVM Light to share my viewmodels over both projects as well. Turns out that, as usual, a good idea is stopped by technical limitations.

The problem

The problem is the difference between Windows 8 and Windows Phone, they don’t share their entire codebase. Meaning I can’t reuse all my code in a PCL. Also the Azure Mobile Services SDK has no portable version, so same problem there.

The solution is abstractions, create an interface for every class that isn’t compatible with the PCL projects and implement them in a platform specific library. The PCLs I’m using only target .net 4.5, winRT and WP8 so a lot of problems are already taken care of by not selecting WP7.X compatibility.

The road so far

I wanted to start out by replacing MVVM Light with the PCL version. This turned out to be easier said than done, the initial project was started from the MVVM Light template so I threw out the references to MVVM Light and added the PCL version through NuGet. Visual Studio went quite mad and started throwing all sorts of weird build errors, I eventually found out that the win8nl library also includes the MVVM Light assemblies and those conflicted with the PCL versions. But I needed the win8nl assembly for the eventtocommand behaviors in WinRT so that posed a big problem. Luckily there’s the winRTBehaviors assembly that contains the logic to do behaviors but it doesn’t include the actual eventtocommand one. The solution was to go to the Codeplex site of win8nl and copy the behavior classes from there and put them in my framework project. One problem solved.

The next step was to add a PCL for the Framework and SDKBroker projects, the Model was already a PCL so that one could stay as it was. The PCL libs got named ComicDB.Framework and ComicDB.SDKBroker, they contain a combination of interfaces and classes. Everything that couldn’t be made portable was abstracted into an interface and implemented in platform specific libraries called ComicDB.Framework.WinRT and ComicDB.SDKBroker.WinRT. The classes that needed abstraction were the NavigationService, Network helper, WAMS service class and Service helper. Thanks to the new portable HttpClient assembly I could copy my RestClient class to a PCL without any adjustments.

With some tinkering I got the project to build and run again and I saw that it was good. The time had come to move my ViewModels over to a PCL. I added a new PCL project called ComicDB.ViewModel (same namespace as my VMs already had) and added the portable MVVM Light version. The ViewModelLocator can’t be moved since it needs to register all the correct interface implementations into the IOC container, so I’ll have a separate Locator class for Win8 and WP8. As I started moving ViewModels I quickly ran into a navigational problem, my viewmodels have navigation logic and the pages they are navigating to aren’t known in the PCL. To solve this I’ve created an interface for every page and set that as navigational target, I don’t know if this will work but I’ll find out soon enough and put it in part 2 if this diary.

Navigational problem solved, on to the next one. Two of my viewmodels could show toast notifications, I use the notifications helper classes from MSDN to get this done but the notification classes aren’t portable (and they really don’t need to be since Windows Phone doesn’t support in-app toasts, the C4F toolkit fixes that luckily) so I created an IMessageAPI interface that has a PopToast() method. In FrameWork.WinRT it shows a build-in toast just like the app used to do.

Hey remember that we have to do everything async now and that we can call the Dispatcher to execute something on the UI thread? Not happening in a PCL… MVVM Light contains a DispatcherHelper that checks if an action needs to be executed on the UI thread and actually executes it there when needed, except in the PCL version. So IDispatcher was born.

With that done I got my project to build again and to run but it’s currently still using the old viewmodels, I expect a whole bunch of new problems when I try to change it to the PCL versions, but that will be for part 2.

What’s next

In part 2 I hope to make the app use the PCL version of the viewmodels and I’ll start working on the Windows Phone project.

Conclusion

PCL projects sound very good in theory but in reality they are a great PITA to work with. Portable HttpClient and portable MVVM Light make them useful but you’ll have to right loads of extra code, abstractions and helper classes to get to something that looks like build once run on two platforms. I could’ve given up and just rebuild everything in a separate solution for WP8 but I want to see how far I can take this and document it along the way.

That said, I have no idea when part 2 will be live, that depends on when I can gather the courage to reference the viewmodel project Smile


Tags:

.Net | Devices | Metro | MVVM Light | PCL | Windows 8 | WinRT | WP8

SQLite in Windows Phone 8: The sequel

by Nico

Read the first part: SQLite with a bit of MVVM Light in Windows Phone 8

Last week I’ve blogged about using SQLite in an MVVM scenario in Windows Phone 8. Since, in my opinion, the post was already getting to an epic length I decided to leave out a part for this week.

I’ll try to keep it a bit shorter this time, should be able to. The part I left out was using relationships and foreign keys with SQLite and the sqlite-net library. I’ll be building upon the project of the previous post, so the task schedule thingy. What we’ll be doing is adding the possibility of creating subtasks so that a task can be divided into smaller tasks. Note that this is just a proof of concept (POC) it’s in no way a complete application and it will have some strange things but that’s the whole fun of a POC.

Let’s kick things off with the creation of a new class for holding the SubTasks.

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

By using attributes we define this class as being a column in the SQLite database and the property Id being a primary key with auto increment. This is all explained in more detail in the previous post. A new attribute here is Indexed on the TaskId property. That attribute states that that property will be an index, it will hold the primary key of the Task table.

Remember that the database was created in the App.xaml.cs? We’ll need to add a line there to create the SubTask table as well. If you haven’t shut down the emulator between the previous post and this one, or you’re testing on an actual device, you’ll need to remove the app so that the database is destroyed or the new table won’t get generated.

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. }
  13.  
  14. private async void CreateDB()
  15. {
  16.     Connection = new SQLiteAsyncConnection("taskDB.db");
  17.  
  18.     await Connection.CreateTableAsync<Task>();
  19.     await Connection.CreateTableAsync<SubTask>();
  20. }

I’ve added the complete snippet as reference, line 19 is the new one.

Next up is the view, this will be quite similar to the Mainpage, a pivot with two pages. One containing a form for adding a new subtask and one containing a list of all subtasks.

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.             <TextBlock Text="Main task ID" TextWrapping="Wrap" />
  13.             <TextBlock Text="{Binding TaskId}" />
  14.  
  15.         </StackPanel>
  16.     </DataTemplate>
  17. </phone:PhoneApplicationPage.Resources>
  18.  
  19.  
  20. <!--  Buttons are defined using the behaviors in the Cimbalino toolkit to allow a bindable appbar  -->
  21. <phone:PhoneApplicationPage.ApplicationBar>
  22.     <shell:ApplicationBar IsMenuEnabled="True" IsVisible="True" />
  23. </phone:PhoneApplicationPage.ApplicationBar>
  24.  
  25.  
  26. <!--  LayoutRoot is the root grid where all page content is placed  -->
  27. <Grid x:Name="LayoutRoot" Background="Transparent">
  28.     <!--  Bindable Appbar buttons  -->
  29.     <i:Interaction.Behaviors>
  30.         <behaviors:ApplicationBarBehavior>
  31.             <behaviors:ApplicationBarIconButton Command="{Binding SaveNewSubTaskCommand,
  32.                                                                     Mode=OneTime}"
  33.                                                 IconUri="/Assets/AppBar/save.png"
  34.                                                 Text="Save Task" />
  35.         </behaviors:ApplicationBarBehavior>
  36.     </i:Interaction.Behaviors>
  37.  
  38.     <Grid.RowDefinitions>
  39.         <RowDefinition Height="Auto" />
  40.         <RowDefinition Height="*" />
  41.     </Grid.RowDefinitions>
  42.     <phone:Pivot Title="SQLite POC" Grid.Row="1">
  43.         <phone:PivotItem x:Name="NewTask"
  44.                             CacheMode="{x:Null}"
  45.                             Header="new subtask">
  46.             <StackPanel>
  47.                 <TextBlock Text="Main task" />
  48.                 <toolkit:ListPicker ItemsSource="{Binding Tasks}" SelectedItem="{Binding SelectedTask, Mode=TwoWay}">
  49.                     <toolkit:ListPicker.ItemTemplate>
  50.                         <DataTemplate>
  51.                             <TextBlock Text="{Binding Title}" />
  52.                         </DataTemplate>
  53.                     </toolkit:ListPicker.ItemTemplate>
  54.                 </toolkit:ListPicker>
  55.                 <TextBlock Text="Title" TextWrapping="Wrap" />
  56.                 <TextBox x:Name="TextBoxTitle"
  57.                             Height="72"
  58.                             Text="{Binding NewSubTask.Title,
  59.                                         Mode=TwoWay}"
  60.                             TextWrapping="Wrap" />
  61.                 <TextBlock Text="Complete by" TextWrapping="Wrap" />
  62.                 <toolkit:DatePicker Value="{Binding NewSubTask.Date, Mode=TwoWay}" />
  63.             </StackPanel>
  64.         </phone:PivotItem>
  65.         <phone:PivotItem x:Name="AllTasks"
  66.                             CacheMode="{x:Null}"
  67.                             Header="all subtasks">
  68.             <phone:LongListSelector ItemTemplate="{StaticResource TaskListItemTemplate}" ItemsSource="{Binding SubTasks}" />
  69.         </phone:PivotItem>
  70.     </phone:Pivot>
  71. </Grid>

The only new thing here is the ListPicker, it’s a control in the Windows Phone Toolkit (get it from NuGet) and it’s kind of like Windows Phone’s version of a combobox. The ItemTemplate is a TextBlock containing the Title of the Task.

If you want details on the bindings, read the previous post. The DataContext for this page binds to a SubTaskViewModel through the ViewModelLocator

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

And here’s the SubTaskViewModel

Code Snippet
  1. public class SubTaskViewModel : ViewModelBase
  2. {
  3.     private readonly IDataService _dataService;
  4.     private readonly INavigationService _navigationService;
  5.  
  6.     private IList<SubTask> _subTasks;
  7.     public IList<SubTask> SubTasks
  8.     {
  9.         get
  10.         {
  11.             return _subTasks;
  12.         }
  13.  
  14.         set
  15.         {
  16.             if (Equals(_subTasks, value))
  17.             {
  18.                 return;
  19.             }
  20.  
  21.             _subTasks = value;
  22.             RaisePropertyChanged(() => SubTasks);
  23.         }
  24.     }
  25.  
  26.     private SubTask _newSubTask;
  27.     private IList<Task> _tasks;
  28.     private Task _selectedTask;
  29.  
  30.     public SubTask NewSubTask
  31.     {
  32.         get
  33.         {
  34.             return _newSubTask;
  35.         }
  36.  
  37.         set
  38.         {
  39.             if (_newSubTask == value)
  40.             {
  41.                 return;
  42.             }
  43.  
  44.             _newSubTask = value;
  45.             RaisePropertyChanged(() => NewSubTask);
  46.         }
  47.     }
  48.  
  49.     public RelayCommand SaveNewSubTaskCommand
  50.     {
  51.         get
  52.         {
  53.             return new RelayCommand(async () =>
  54.                                                 {
  55.                                                     NewSubTask.TaskId = SelectedTask.Id;
  56.                                                     await _dataService.Save(NewSubTask);
  57.                                                     SubTasks.Add(NewSubTask);
  58.                                                     NewSubTask = new SubTask { Date = DateTime.Today };
  59.                                                 });
  60.         }
  61.     }
  62.  
  63.     public IList<Task> Tasks
  64.     {
  65.         get { return _tasks; }
  66.         set
  67.         {
  68.             if (Equals(_tasks, value))
  69.             {
  70.                 return;
  71.             }
  72.  
  73.             _tasks = value;
  74.             RaisePropertyChanged(() => Tasks);
  75.         }
  76.     }
  77.  
  78.     public Model.Task SelectedTask
  79.     {
  80.         get { return _selectedTask; }
  81.         set
  82.         {
  83.             if (Equals(_selectedTask, value))
  84.             {
  85.                 return;
  86.             }
  87.  
  88.             _selectedTask = value;
  89.             RaisePropertyChanged(() => SelectedTask);
  90.         }
  91.     }
  92.  
  93.     public SubTaskViewModel(INavigationService navigationService, IDataService dataService)
  94.     {
  95.         _navigationService = navigationService;
  96.         _dataService = dataService;
  97.         SubTasks = new List<SubTask>();
  98.  
  99.         NewSubTask = new SubTask { Date = DateTime.Today };
  100.         GetData();
  101.     }
  102.  
  103.     private async void GetData()
  104.     {
  105.         Tasks = await _dataService.LoadTasks();
  106.         SubTasks = await _dataService.LoadSubTasks();
  107.     }
  108. }

In this viewmodel we’ll have a list of both the Tasks and the SubTasks because we’ll have to select a Task to attach a SubTask to. The constructor loads in the NavigationService and the DataService from the Ioc container, Tasks and SubTasks get loaded and we’re good to go. Now the navigation isn’t really what it should be in this POC, because you have to go to a Task edit page, click the Add Subtask button and then select the Task you want to create a subtask for, it’s a bit of double work but I don’t care Smile.

Remember the DataService? It’s the class that takes care of all the CRUD operations in our app, it’ll need to do the same for the subtasks. I’m a bit lazy, so I’ve only did the insert and read part. Here’s the read snippet

Code Snippet
  1. public async Task<IList<SubTask>> LoadSubTasks()
  2. {
  3.     return await App.Connection.Table<SubTask>().ToListAsync();
  4. }

Exactly the same as for reading out the Tasks. Now, for saving I altered the SaveTask function to be generic.

Code Snippet
  1. public async Task Save<T>(T newTask)
  2. {
  3.     await App.Connection.InsertAsync(newTask);
  4. }

This function takes in basically anything and saves it in the DB, if you pass something in of a type that doesn’t have a table in the DB the app will crash, hard. So be careful how you use this and you might think of adding some error handling.

And there we are, a working SQLite proof of concept with relationships and everything. Since a picture says more than a thousand words, here are some screenshots.

The Edit Task screen with the Add subtask button

The Add SubTask screen with all the Tasks in a listpicker

List of SubTasks with the Task ID

The entire project can be downloaded in a zip file here (Link to my SkyDrive).


Tags:

.Net | MVVM Light | Metro | WP8 | sqlite

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