Sunday, September 25, 2011

MVVM Step By Step, part I

Since we are doing quite a lot of Silverlight, WPF and Windows Phone 7 development at QFrame, we also train our new people in patterns like MVVM. For future reference I thought it would be nice to write the basics of our MVVM session down. It is actually a step by step approach to implementing MVVM in a Silverlight application (which is usable in WPF and Windows Phone development as well). I also don't use any predefined framework in the initial explanation of the MVVM pattern. This is to let you see what can be done without using frameworks and for which parts some library functionality might be nice.

As a startup, I will create a simple Silverlight application which is hosted in a ASP .NET web application. In the ASP .NET web application I will also place a small WCF Data Service, which will provide the model data I will use in the Silverlight MVVM app. The database (a simple mdf file) contains two tables customers and companies. I created an Entity Data Model for these in the ASP .NET web application and hosted them in a WCF Data Service. The data service looks like this:


public class CustomerService : DataService<CustomersEntities>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("Customers", EntitySetRights.All);
        config.SetEntitySetAccessRule("Companies", EntitySetRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

This is the initial project setup:


The service reference to the CustomerService is already present in the Silverlight project.

First thing I do in a new MVVM application, is creating separate folders for my models, views and viewmodels. In this demo, my model will consist of simple data classes, but actually my service is also part of my model. My models, viewmodels and views will all be placed in the same project, but this is not a necessity.



For the application I am building, I want a kind of menu on the left of the screen, with links to, for instance, an 'all customers' page, a 'new customer' page, an 'all companies' page and a 'new company' page. On the right of the page the corresponding page will be shown. To achieve this, I will create a new view, called MainView.xaml in which I place a couple of buttons and a ContentPresenter.

<UserControl x:Class="Demo1.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="30*" />
            <ColumnDefinition Width="70*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0" Background="AliceBlue">
            <Button Content="All Customers" Margin="10" />
            <Button Content="New Customer" Margin="10" />
            <Button Content="All Companies" Margin="10" />
            <Button Content="New Company" Margin="10" />
        </StackPanel>
        <ContentPresenter Grid.Column="1" />
    </Grid>
</UserControl>


Now, since we are using MVVM, I also need to create a viewmodel to go with this view. So, in the ViewModels directory I will create a new class and call it MainViewModel.

namespace Demo1.ViewModels
{
    public class MainViewModel
    {
        
    }
}

We now have our view and our viewmodel. If we'd run this application now, this wouldn't show much on our screen yet. In fact, you would see a blanc page. This is because the application is still wired up to show the default xaml page. Open up your app.xaml.cs file and you'll see the following piece of code.

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
}


This will have to be changed so your MainView is set to the RootVisual of the application. And also, the view (MainView) and viewmodel (MainViewModel) will have to be linked to each other. Now, for this, there are two options. Either your view knows who its viewmodel is (view-first) or it doesn't (viewmodel-first). I will use the viewmodel-first approach.

To link the two up, change the default code in app.xaml.cs as follows:


private void Application_Startup(object sender, StartupEventArgs e)
{
    var view = new MainView();
    var viewmodel = new MainViewModel();
    view.DataContext = viewmodel;
    RootVisual = view;
}


If you would do this linking view-first, you would set the DataContext property in the xaml of your view. In this demo I've chosen to use the viewmodel-first approach.

After doing this, and running the application, you will get to see your view. pressing the buttons, however, will not have much effect, yet. We will make them send messages to your viewmodel in the next part.

Thursday, September 22, 2011

Highcard Game: First App in the Marketplace

At QFrame, we are very proud to announce that as of today, we've got our first app up and running in the Windows Phone Marketplace.


It is a very simple game, based on the drawing of cards, which can be played from 2 up to 4 players. After a draw, the highest card wins. It is excellent to use if you'd need to decide who needs to do the dishes, who should go for bread in the morning or, who should pay the next round of drinks, ...

This little experiment thought us a lot about the basics of Windows Phone development and about the approval process. We were revoked at first for the marketplace, since we only took a dark background into account. This was an easily fixed issue, though.

So, if you're interested, go and download it to your phone, and let us know what you think about it.

Mobile Cross Platform MV Solution

After the initial hours lost on installing everything, I have been playing some more with MonoDroid lately, trying to port a basic Windows Phone 7 application to an Android device. Part of this was quite easy (thanks to MonoDroid that is) and part of it took some refactoring of the existing code. All in all, the experience was very insightful.

The existing WP7 application uses the MVVM pattern, which makes it very easy to get a separation of concerns between your model, view and viewmodel (I sometimes like to rant about this separation of concerns not being as clear as it should be in some applications). It also works very well in combination with the databinding that is provided in Silverlight. If you want to know more about the MVVM pattern, check out the article by Josh Smith in MSDN Magazine.

While MVVM works very well with Silverlight, WPF and Windows Phone apps, I did have some issues using this pattern in combination with MonoDroid. Let me walk you though this.

I started off thinking which parts of the existing code I would be able to reuse for the Android application. Reusing the views was out of the question, since Android views are written differently than Windows Phone views. But my models should be easily reusable, as should be my viewmodels.

The existing application already had the model and viewmodel classes in a separate Windows Phone class library. The views were contained in a Windows Phone 7 application (MemoChallenge.Wp7). So, reusing the models and viewmodels, would just be a matter of using this same class library for my Android application. Now, you can't just reference a Windows Phone 7 class library in an Android project. For this to work you need a second class library, specific for the Android/Monodroid project and some clever project linking.

For the Android application I actually created two more projects, one for the Android  views (MemoChallenge.droid), and one class library (MemoChallenge.droidlogic), which would be a linked project to the Windows Phone 7 class library (MemoChallenge.logic). You can use the Project Linker tool for this. This will link the two class library projects and will make sure that any change you do in one project, gets reflected in the other project.


After doing this, I immediately got my first compile errors, and they were abundant. Why did I get all these errors?

The thing is, viewmodel classes use commands all over the place. Or actually, they use the ICommand interface. This interface turned out to be quite a big problem. It is contained in a Windows specific dll, so the Android SDK does not know what to do with it.

To solve this problem, I could have rewritten the ICommand interface for Android. This would also mean I would have to add conditional compilation attributes all over the viewmodel code. I was not willing to do this, since it would be a lot of work. And I am not that fond of conditional compilation attributes.

Instead I used a combination of the MVVM and MVP pattern. I did not want to throw away the existing viewmodels, since they were working just fine. I did move them though, to the views project (MemoChallenge.Wp7), so they were no longer present in the shared class library. As a replacement for the Android application (and the WP7 application, remember these projects are linked), I added presenter classes. My viewmodels became very slim, I practically removed all of their logic and moved it all to the corresponding presenters. Now only thing my viewmodels had to do is forward the call to a presenter and we're done.

   public class GameViewModel : ViewModelBase, IGameViewModel 
   { 
     private ICommand _startCommand; 
     private ICommand _sameCommand; 
     private ICommand _notSameCommand; 
     private GamePresenter _presenter; 
     private IGameData _gameData; 

     public GameViewModel() 
     { 
       _presenter = new GamePresenter(this); 
     } 

     public ICommand StartCommand 
     { 
       get 
       { 
         if (_startCommand == null) 
           _startCommand = new RelayCommand(() => _presenter.Start(), 
             () => _presenter.CanStart()); 
         return _startCommand; 
       } 
     } 

     //rest of the code omitted 
 }  

I hope this gives you an easy way to get MVVM to work on Android/MonoDroid.

Tuesday, September 20, 2011

dotnetAcademy

At QFrame we are very committed to get our new, young people quickly up to speed with .Net development. To achieve this, we have started with the dotnetAcademy project in which we give our youngster all the necessary info to become good developers. This also allows us to get them up to speed with new technologies once they get on the job.

For the dotnetAcademy we work together with bitconsult, who have already been giving this kind of training for some time now. The training itself consists of actual workshops on topics they will need in real application development (WCF, patterns, ALM, ... to name a few), training on presentation and communication skills, and an internal project they will be developing during the next two months. This project will also be closely monitored and coached by myself as will I give some of the workshop trainings.

Starting this week, our junior programmers have also started blogging. You can read about their experiences at the dotnetAcademy site. Check it out, I'd say.


Saturday, September 17, 2011

Some MVVM Badness

I must say, I really like the MVVM pattern for doing both Silverlight and WPF development. I have been using it for quite some time now, with and without a standard framework. And although I really like the pattern, I have also seen some bad code pop-up in applications that are more like anti-MVVM. The reason for this is that the responsibilities of each part of the MVVM pattern get mixed up. People seem to think that once their class has the 'ViewModel' extension it actually behaves like a viewmodel, which is not always the case.

For starters, I have seen people use MVVM without the first M. That is, people tend to do MVVM without a model and just put everything in their viewmodel, even their model data. It pops up like private data members in the viewmodel, where they actually should use a model. The temptation for doing this can be quite big, since often you have to put propertychanged notifications in your viewmodel. It just seems that much easier to skip the model for this. The temptation seems to be biggest in applications where there is no real back-end, like a service, that needs to be called, that hands you off something model-ish.

Another sin in MVVM applications is the over-use of the commands in a viewmodel. They are there as a hook for your view to tell the viewmodel to 'do something' or that 'something needs to be processed'. This doesn't mean that all of the logic for the something that needs to be done, has to be put in the viewmodel. It is ok for the viewmodel to ask some other component to handle the details of the something that needs to be done. For this, keep the rule of single responsibility in mind. The moment your viewmodel starts to do more than what it's supposed to do, you probably need to refactor out some of the logic (maybe hand it of to the model or to some other component).

Your viewmodel should only have the logic for bridging between your view and your model. It is there to present the data of the model in such a way so that it makes sense to the view. And it also contains commands so that the view can interact with the model. And that is all it should do. This also implies that the model can be (even has to be) more than just a POCO or DTO, it can contain logic if it needs to. This is often a misconception in MVVM, where the model is seen as just a class that contains data. But this is often not the case. Often, the model is a back-end, which contains business logic and which hands you off POCO or DTO classes. Often it is more than just one model class, it can be a whole bunch of classes, all interacting to provide your viewmodel with services.

A last offense can be found in the view. It is still ok to put logic in the xaml.cs file, but make sure you limit this to view-specific logic. That is, for instance, the logic that is needed for a certain animation to display properly. And that's all. All of the other logic should be in your viewmodel or should be delegated from your viewmodel to other components. So don't start putting state specific logic in the code behind of the view. This means that, if you have animation specific code in your code behind, the actual check 'IsAnimating' should be in your viewmodel.

That's the end of my MVVM pattern rant. I really really like this pattern, but just keep in mind that it is not because you use a certain pattern, your code keeps to it. Keep the different responsibilities of each part of the pattern in mind, so you don't accidentally mix them up.

Friday, September 16, 2011

Resharper Shadow Copy

When running your unit tests with ReSharper, apparently your assemblies all get copied to a temporary directory, where your project gets build and in which the actual tests are run. This allows you to start a second build of a project, while your tests are still running. Handy as this might be, it does give problems sometimes. If, for instance, some of your tests rely on additional files to be present in your output directory (like resource files), they will not be found, since they are not being copied to the temp directory in which the ReSharper tests run.

Only option is, to turn off the shadow-copy capability in the ReSharper Options window. Now your tests will be run in your actual output directory.



I ran into this issue with classes that utilize Assembly.GetExecutingAssembly to get the full file path to a resource. While my test cases ran fine while using the MSpec runner (which uses a rake script which copies all necessary files), they failed using the NUnit runner utilized by ReSharper. Turning of the shadow-copy option resolved the problem.