Saturday, October 15, 2011

MVVM Step By Step, Part III


In the previous posts, which you can find here and here, we created a first, simple MVVM app. We already set up some basic databinding between our view, MainView, and viewmodel, MainViewModel, to show something in the ContentPresenter of the view. What we still need to do, however, is react to the button clicks of the buttons present in the MainView. In a normal, non-MVVM application, you would use eventhandlers for the button clicks. This is, however, something we will not do in an MVVM application, mostly because we want our viewmodels to be testable. Instead off an eventhandler with a sender object and eventargs, in MVVM, we create properties of the ICommand interface.

ICommand properties are properties which return a type that implements the ICommand interface. They are bindable to commands in a view, like the Command property of a Button. And second, they consist of an Execute and CanExecute method. The combination of these two gives a nice way of indicating which code needs to be executed and whether or not it can be executed. On the downside of ICommand properties is the fact that they can only be bound to commands in a view and not to events. This is why a lot of MVVM frameworks add an EventToCommand kind of type which makes it possible to bind ICommand properties to events. More on that in a later post.

For now, let's add a first ICommand property to the MainViewModel and bind it to the Command property of a button. Let's start with the ICommand for a new customer, the NewCustomerCommand.

public class MainViewModel
{
    private ICommand _newCustomerCommand;

    public ICommand NewCustomerCommand
    {
        get
        {
            if (_newCustomerCommand == null)
                _newCustomerCommand = new NewCustomerCommand();
            return _newCustomerCommand;
        }
    }
}

The NewCustomerCommand is a class we still need to write, so lets add it to our solution. I prefer adding an extra Commands folder for these kinds of classes (not that we will be creating much of them, you will soon see why). Since the NewCustomerCommand needs to implement the ICommand interface it will initially look like this.

public class NewCustomerCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        throw new NotImplementedException();
    }

    public void Execute(object parameter)
    {
        throw new NotImplementedException();
    }

    public event EventHandler CanExecuteChanged;
}

Since there are no restrictions on executing this command, we will have the CanExecute method always return true. The Execute method needs to open the NewCustomerView within the ContentPresenter of the MainView. We will again use the same technique of initializing a view and viewmodel and then binding the two together using the DataContext property of the view (didn't we do this three times allready? As any good (lazy) programmer, might we not think about making this something more generic??? Yes, we will, but not yet).

public class NewCustomerCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        var view = new NewCustomerView();
        var viewmodel = new NewCustomerViewModel();
        view.DataContext = viewmodel;
    }

    public event EventHandler CanExecuteChanged;
}

Now that we have this view, we need to assign it to the ViewToShow property of our MainViewModel. This is kind of hard, since the NewCustomerCommand and the MainViewModel don't know each other. We need to add a constructor to the NewCustomerCommand that takes the MainViewModel as a parameter and then uses it as a private datamember. Now we can assign the ViewToShow property.


public class NewCustomerCommand : ICommand
{
    private MainViewModel _mainViewModel;

    public NewCustomerCommand(MainViewModel mainViewModel)
    {
        _mainViewModel = mainViewModel;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        var view = new NewCustomerView();
        var viewmodel = new NewCustomerViewModel();
        view.DataContext = viewmodel;
        _mainViewModel.ViewToShow = view;
    }

    public event EventHandler CanExecuteChanged;
}

The call to this constructor in the MainViewModel needs to pass itself (this) now to the NewCustomerCommand.


public ICommand NewCustomerCommand
{
    get
    {
        if (_newCustomerCommand == null)
            _newCustomerCommand = new NewCustomerCommand(this);
        return _newCustomerCommand;
    }
}

The only thing left now, is add a binding to the MainView so the Command property of the NewCustomer button is bound to the NewCustomerCommand property.


<Button Content="New Customer" Margin="10" Command="{Binding NewCustomerCommand}" />

Again, add a TextBlock with some dummy text to your NewCustomerView to test this out. If you run the application you will find, however, the NewCustomer button does not seem to work. Clicking it, will not result in the other view being shown. If you place breakpoints in your code however, you will see that the Execute method of your NewCustomerCommand does get called.

What is actually wrong is the fact that the ViewToShow property gets a new value, but it does not announce this fact. For this you need the INotifyPropertyChanged interface. Implement it in your MainViewModel and change the ViewToShow property from an autoproperty to a property with a backing field and call the PropertyChanged event.

public class MainViewModel : INotifyPropertyChanged
{
    private ICommand _newCustomerCommand;
    private FrameworkElement _viewToShow;

    public MainViewModel()
    {
        var view = new AllCustomersView();
        var viewmodel = new AllCustomersViewModel();
        view.DataContext = viewmodel;
        ViewToShow = view;
    }

    public FrameworkElement ViewToShow
    {
        get { return _viewToShow; }
        set
        {
            _viewToShow = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("ViewToShow"));
        }
    }

    public ICommand NewCustomerCommand
    {
        get
        {
            if (_newCustomerCommand == null)
                _newCustomerCommand = new NewCustomerCommand(this);
            return _newCustomerCommand;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}


If you now run the application, you can use the NewCustomer button to show the other view.

In a next post I will show you how to add some more framework-like capabilities. As in, how can you provide certain parts, so you don't need to rewrite masses of code every time you need to add something new (like a new command).

Monday, October 10, 2011

MVVM Step By Step, part II

In the previous post, we created the initial setup of an MVVM application. We already created a first view, MainView, and a first viewmodel, MainViewModel. Both were hooked up using the DataContext property of the view. What we didn't do yet, was show something in the ContentPresenter on the MainView.

Initially, we want to show all of the customers. In our MVVM app, this will be another view, AllCustomersView, and another viewmodel, AllCustomersViewModel. It will be the responsibility of the MainViewModel to initialize these two. The basics of hooking the view and viewmodel together will be similar to what we did for the MainView and MainViewModel. Lets initialize all this in the constructor of the MainViewModel.

public MainViewModel()
{
    var view = new AllCustomersView();
    var viewmodel = new AllCustomersViewModel();
    view.DataContext = viewmodel;
}

For the AllCustomersView just create a new UserControl in your views folder. For the AllCustomersViewModel, create a new class in your ViewModels folder.

Now that we have this view and viewmodel, we need to be able to show them in the ContentPresenter of the MainView. For this, you will need a property in your MainViewModel to which the MainView ContentPresenter can bind to. We will add this property to the MainViewModel class.

public FrameworkElement ViewToShow { get; set; }

Make sure you assign the view you created in the constructor to this property.

public MainViewModel()
{
    var view = new AllCustomersView();
    var viewmodel = new AllCustomersViewModel();
    view.DataContext = viewmodel;
    ViewToShow = view;
}

Last thing you need to add is the binding in your view.

<ContentPresenter Grid.Column="1" Content="{Binding ViewToShow}" />

Just for testing purposes, you can add a TextBlock with some dummy text in your AllCustomersView and run the application. You should see the content you placed in your AllCustomersView in your application.

That's it, as simple as that. A viewmodel provides properties for your view to bind to. In the next post we will see how we can react to the clicks of the buttons in the MainView.

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.