Nico's digital footprint

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

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

WinRT: GroupedGridView first item other template

by Nico

I’m currently building a comic application for Windows 8, yesterday I was building the page where users can see the details about a certain comic issue. The idea I had for this page was that on the left was the cover of the issue, followed by a list of characters appearing in the issue. A grouped GridView would be perfect for this scenario but it only accepts one template, so all groups usually look the same. Here’s the way that I’ve fixed it, I’m not 100% happy with it but it works. If you have a better way, please tell me, I’ll update this post accordingly and give credit where credit is due off course.

Let’s start off with the class. I have a class called Issue that obviously contains all the information about an issue.

public class Issue
{
    public int Id { get; set; }
    public bool IsImage { get; set; }
    public string Name { get; set; }
    public string Image { get; set; }
    public List<Character> Characters { get; set; }
}

Notice the IsImage boolean? That one’s the key to the whole thing. The image itself is just a string to an image on the web. Next up is the Character class.

public class Character : INotifyPropertyChanged
{
    public string Name { get; set; }
    public bool IsImage { get; set; }

    private string _image;

    public string Image
    {
        get { return _image; }
        set
        {
            if (_image == value)
                return;

            _image = value;

            RaisePropertyChanged("Image");
        }
    }

    public Character()
    {
        IsImage = false;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

}

Again in this class a boolean called IsImage. This time however the boolean has an initial value of False set in the constructor.

A third class is a generic class that will contain all collections to be shown in every group in the GridView

public class GroupInfoList<T> : List<object>
{
    public object Key { get; set; }

    public new IEnumerator<object> GetEnumerator()
    {
        return base.GetEnumerator();
    }
}

This is a pretty basic implementation that you will find on many blogs and samples about grouped GridView.

The next step is in the viewmodel, where I’ll load in the data and prepare everything to be shown in the Grouped GridView.

private async void LoadData()
{
    IssueGroups = new ObservableCollection<GroupInfoList<object>>();
    var issueDetails = await _service.GetIssueDetail(SelectedIssue.Url);

    var cover = new GroupInfoList<object> { Key = "Cover" };
    SelectedIssue.IsImage = true;
    cover.Add(SelectedIssue);
    IssueGroups.Add(cover);

    var info = new GroupInfoList<object> { Key = "Characters" };
    info.AddRange(issueDetails.Characters);
    IssueGroups.Add(info);
}

First I create an ObservableCollection of type GroupInfoList, the class I’ve created in the previous step. Then I’ll ask my service to get me all the details of the issue. Once I have all the info I start dividing it into the groups that I want it shown on the page. I wanted to start off with the cover in the first group but I can’t just put the image url in the group because that way I can’t pass anything to my converter later on. So instead I just put the entire issue object in the first group and I set the IsImage property to True.

The second group will contain all the characters, remember that Character sets IsImage to false in the constructor, so no need to do that here explicitly. I now have everything set to show two groups in my GridView. Onto the XAML we go.

So now we reached the actual problem. We can set one ItemTemplate but I need two. Here’s what my template looks like.

<GridView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
            <Border BorderBrush="Black" BorderThickness="2" Width="300" HorizontalAlignment="Left"
Height="120" Visibility="{Binding IsImage,
Converter={StaticResource KeyToVisibilityConverterReverse}}"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0,0,0"> <Image Source="{Binding Image}" Height="100" /> <StackPanel> <TextBlock Text="{Binding Name}" Width="180" Foreground="Black"
Margin="12,0,0,0" TextWrapping="Wrap" /> <TextBlock Text="{Binding Role}" Width="180" Foreground="Black"
Margin="12,0,0,0" TextWrapping="Wrap" /> </StackPanel> </StackPanel> </Border> <Image Source="{Binding Image}" Height="500" Visibility="{Binding IsImage,
Converter={StaticResource KeyToVisibilityConverter}}" /> </StackPanel> </DataTemplate> </GridView.ItemTemplate>

I've build a stackpanel that contains both my templates, one is just a simple image bound to the cover image. The second is a border containing a smaller image and a few textboxes. And as you can see, the Visibility of both templates are bound to IsImage. Now I have two converters to bind too, one has to return “Visible” when IsImage is True while the other one has to return “Collapsed”. Here’s what the converters look like.

public class KeyToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (bool)value ? "Visible" : "Collapsed";
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

public class KeyToVisibilityConverterReverse : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (bool)value ? "Collapsed" : "Visible";

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

And that did the trick for me, this is what my result looks like.

 

I hope I helped some people out with this. Like I’ve said at the beginning of this post, this feels more like some sort of dirty hack than a decent solution but it works. Please let me know if you have another way of doing this.


Tags:

.Net | MVVM Light | Metro | Windows 8 | XAML

Windows 8 Summer app-a-thon

by Nico

Last week, on June 12, Microsoft Belgium organised a Windows 8 App-a-thon. Place to be this time was the casino in Blankenberge, a city at the Belgian coast. The concept: two app-a-thons, one during the day and one during the night. Gather a team, build an app in a few hours and show it off to the rest.

As usual I arrived a few hours early, always prefer arriving early then arriving late and have an entire room stare at you as you enter. The room was quite big, there were about 50 registrations for the event, a small and entertaining group. Once everyone of the day group arrived and got setup the introduction of the day began. Katrien De Graeve, a Microsoft Belgium Evangelist, gave the intro with me giving a small demo of Trello, the online board system that the app-a-thon community is using to divide the groups and brainstorm about different ideas.

   


After all the introductions were done, it was time to grab the first Red Bull of the day and started coding. My team would arrive for the night so during the day I mostly worked on my ComicDB app. This was also my first public appearance as a MEET member. This meant I would be a helper on people getting stuck. I did help some people with small issues and it felt good, being part of a community means helping people out and getting help from others. And you get fancy t-shirts Glimlach.

   


There were no demos after the day event because most teams stayed to continue working on their app during the night. Between both events it was time to get out and get some ice cream and seeing the beach. Yes that’s right, a bunch of developers went out to the beach instead of staying in a room behind a computer.

 

Then it was time for the night event, while eagerly awaiting the pizza me and my newly arrived team started working. We were working on a XBMC remote for Windows 8. We’ve spent some time before the event getting to know the API (which is a JSON-RPC API) and started working an a .NET wrapper for it. Our team proved to be pretty efficient and new functionality got spit out constantly. Never the less we couldn’t get all functionality working, playing a movie from within the app proved to be a big challenge, something we’re currently still working on.

After some pretty darn good slices of pizza and some hours of coding it was demo time. Some impressive apps got shown off, an app to check the type of beer based on its color, an app that provides you with color schemes that you can use, a MovieDB app and a random funny sentence generator (that one was pretty hilarious).

After that we got one more cocktail at the beach and then it was time to get to the parking lot in the rain and start heading home. It was a very fun day, met some nice people, met some people in real life that I know from Twitter and had a great time working with friends on an app.

I can’t wait for the next app-a-thon in August! And the one in September that the community is currently begging for Glimlach

 

PS: About our XBMC remote app, we are currently still working on it and we do plan to get it in the store. At that time it will also get open-sourced. The name is currently MetroRemote but that can still change.

All my pictures can be found here, should you be on one and wish for me to remove it please send me an email or contact me through Twitter


Tags:

.Net | MVVM Light | Metro | Windows 8 | XAML | Community

My community day session slides and demos are online

by Nico

Yesterday was Community Day, the biggest community driven event in Belgium.

I did a talk there about porting over a Windows Phone 7 app to Windows 8. It was very exciting, I never spoke to such a crowd before, let alone hooked up my portable to a cinema beamer.

The talk itself went pretty well but I did suffer from demo failure, what was really odd since the demo worked perfectly an hour earlier. I researched the error after the talk and it seems that in a Windows 8 Metro app the path to the manifest file is an absolute path for some reason. I suddenly remembered that I moved the solution to another folder right before the talk, so it was my own fault. Reminder to self: never move a folder before doing a talk.

Anyway, it was a great day, I've met some nice people, had fun discussions and attended an App clinic on UI (thanks Lesley for the useful information!). See you next year community day!

Download my slides and demos here.


Tags:

.Net | Metro | MVVM Light | Presenting | Windows 8 | WinRT | WP7 | XAML

Filtering collections from XAML using CollectionViewSource

by Nico

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

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

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

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

public enum Pivot
{
    First,
    Second,
    All
}

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

This is the viewmodel

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

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

            items = value;
            NotifyPropertyChanged(ItemsPropertyName);
        }
    }

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

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

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

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

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

This is the template.

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

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

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

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

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

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

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

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

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

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

 

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

Download the Demo project here.


Tags:

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

Techdays Belgium 2012

by Nico

So Techdays is right around the corner and I’ll be attending for the third time.I’ll be attending all kinds of sessions going from Windows 8 development to the complete deep dive track on web to my favorite subject, Windows Phone 7 development. I’m also excited about the Scott “The Gu” Guthrie doing the opening keynote and doing a session the second day. Also presenting this year is Laurent Bugnion, the father of the awesome MVVM Light framework.

Here’s the list of sessions I’ll be attending, this list is subject to change depending on if I change my mind the last minute, as I’m known to do sometimes Glimlach.

Tuesday February 14th

  • Opening keynote with Scott Guthrie
  • Welcome to the Metro Application Platform
  • Windows Phone Fast App Switching, Tombstoning and Multitasking
  • The Future of C# and Visual Basic
  • Devices + Cloud: Using Azure on iOS, Android, Windows Phone, …

Wednesday February 15th

  • ScottGu unplugged
  • Take a ride on the Metro
  • The zen of async: Best practices for best performance
  • MVVM Applied: From Silverlight to Windows Phone to Windows 8
  • MVVM & WCF RIA Services: an architectural story
  • Building a data intensive application

Thursday February 16th

This is a deep dive day, I’ll be following the web track that focuses on what’s new in ASP.net 4.5 and Visual Studio 11

 


Tags:

.Net | Presenting | WP7 | Windows programming | XAML | XNA | Web development | MVVM Light | Devices

  Log in

About the author

Hi,

My name is Nico, I’m an MCP living in Belgium.
I’m currently employed as a consultant in the Mobile Solution Center at RealDolmen, one of Belgium’s leading IT single source providers, where I focus on Windows Phone and Windows 8 development.

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.

This blog will be about Windows Phone 7, C#, XNA , WPF, Silverlight, and much more!

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

 

 

MeetLogo

 

MVBLogo

mybook

 

mybook

 

Month List