If you’ve been writing Windows apps for more than a few weeks, you’ll probably have read an article or heard someone mention “MVVM”. MVVM is one of those things that is easy to file away in the back of your mind as something you probably should know about, and therefore something you might feel a bit guilty about not knowing or doing more about. And the more you think you should know about it, the more you think it’s probably too late to do anything about it, and you’re coding soul is damned forever, so there’s no point even starting now.
Well, I’ve some good news for you. MVVM is not as bad as you think. Sure, if you start Binging around for MVVM web hits you’ll end up reading in-depth (and frankly scary) articles about or by Martin Fowler and wondering how you managed to write any code without knowing any of this stuff. And if you overhear any coding conversations in Redmond Starbucks you might quickly get very lost and feel inadequate, but, hey that’s just normal and you shouldn’t really be eavesdropping anyway, should you?
So today, I’m going to take a stab at explaining what MVVM is, hopefully well enough that you can bluff your way through a conversation at a party frequented by Microsoft developers (and I’m sure those are real, just because I’ve never been to one I’m sure they still exist and are a complete riot).
Design Patterns
If you have been working on other platforms for a while, you might have heard of the subject of design patterns, and MVC in particular. Design patterns provide a ‘big picture’ as to how you might structure your app. It’s nothing to do with a particular programming language, it’s all about how you can divide up the work into components, with the overall aim of making your code easier to read, test, re-use and maintain. Think of it as learning good coding habits.
MVC is one of these patterns, and stands for Model, View and Controller. It’s about keeping your programs data, UI and ‘logic’ in separate chunks. If you have been developing for iOS using Xcode, you’ll have bumped into the MVC design model – the way the UIViewControllers work is pure MVC, but the problem is that it’s so easy to wander completely off the MVC path and lose all the benefits you might not even have realized you are doing it, especially in smaller apps. Here’s a rather nice article on using Xcode and the MCV design pattern properly.
Now, here’s the thing: these design patterns are all just guidelines. There’s no compiler warnings when you do them “wrong”. If you want to use them, you have to bring the discipline to your projects yourself. In many cases, perhaps smaller apps for mobile devices written by one person, there’s not a strong case to be made to enforce this design.
However, as apps get larger, and more and more people besides you get involved, and more testing is required.. well, soon it becomes very apparent that there are some really good reasons to dig deep and find the inner strength to use a design pattern.
Some developers might say that as your career progresses from noob to experienced developer, you go through several stages:
First, you’re just glad that your app mostly works and doesn’t cause the computer to catch fire.
Then you start to write your code in such a way that you can actually read it a few weeks later, and don’t feel too bad if someone else reads it.
Then you realize you need to be using a Source Code Management system like Git (see Visual Studio Online) so you can sensibly back-up your code, manage releases and work with other developers.
And then, after that, you’ll start to wonder if design frameworks can help you when writing larger projects, so you don’t go insane after you’ve written 20,000 lines of code and it’s all in one class.
Finally, you want to make beautiful code. Code that is clear, and legible and something that you can re-use and test and generally rely on. A mix of poetry and engineering, and yes, you really should get out more.
Me? I’m still at the stage when I’m relieved when my phone doesn’t explode, but a man can dream..
MVVM
MVVM is a very difficult to pronounce palindromic acronym, which doesn’t help. Mumvveemmm? It stands for Model, View, View Model. Yes, it’s similar to MVC but it takes advantage of some C#/XAML features to help instill some discipline to keep you on the right track.
Let’s look at the components separately, to get a better understanding of how it works.
1. View
The “View” is the easiest part to understand: it’s the part you look at. In our world, this is the XAML that defines the various controls that make up the app.
When creating non-MVVM apps with buttons and gridviews and all the other XAML controls, you may have linked the controls (in the sense of doing something when they are clicked, or writing code to populate them) directly to handlers in the code behind page, just as in iOS when you would have used the Action event to trigger a method when a button was tapped, or set up a Delegate to popular a UITableView. But then something bad happens: the code behind pages become huge and before you know it, gigantic and the heart of your app is trapped in these classes which are mostly for servicing a user interface.
This direct linkage is not what MVVM is about. In fact, if your XAML controls all link into the C# code-behind page, you’re not doing MVVM at all. To do MVVM well you need to minimize the amount of code you have in the code behind. If you don’t, it’s too easy to end up with your entire app stuffed into the C# code behind, responding directly to Click events. This is OK (probably.. possibly.. maybe?) for smaller apps, but it definitely isn’t OK for larger projects.
When coding in the MVVM pattern, you need to create an abstraction between your buttons and other controls and the main app that makes decisions. This might seem odd: why pull things apart in this way? Won’t it make your application harder to understand?
The argument in favor of MVVM is actually based in pragmatism: you know that after you’ve been working on an app for a while, you lose the idealized purity of the vision you had when you started, and you end up with lots of ‘special cases’ and extra tests, and basically things can get messy. In a project which is larger in scope than a typical app, or which has multiple people working on it, it can get very difficult to try and grok what the code is actually doing.
MVVM tries to mitigate this, by cleanly separating the UI side and the program logic side. There is some extra expense involved, but in the long term, it can make projects considerably more manageable.
2. View Model
So, how do you link your XAML controls with your code? That’s where the View Model, and our old friend data binding comes in. We’ve already seen how we can link data to, say, a ListView. Essentially, you set up the XAML control to be bound to a specific source (an array or list – often an ObservableCollection in fact) and then you can just let it be: the XAML control will display the contents of the array and it can also update the array if the information changes. That’s the power of data binding: you get to write less code. We’ve also seen some slightly more advanced binding, which uses data convertors to take a data source and make that control the color or visibility of a button. XAML is nothing if not flexible.
Therefore, for each of your XAML pages, you should create a new class containing the View Model. Rather than the XAML pages’ code-behind files, it’s these pages which will handle the actions from the user interface, and provide the data to any controls that need it. Here's a before and after for what we hope to achieve:
BEFORE
AFTER
By doing this, we immediately split the UI from the code that services the UI. The downside is that we now need to do a little (ahem) work in order to create the plumbing required to link the XAML side with the View Model side, and this work can be a little bit tricky the first time you try it. In fact, it’s this work which can be the most off-putting part, because at this stage is often seems like a completely unnecessary way of making things difficult for yourself. However, stick with it. It's not quite as bad as you might think. We’ll look at one approach in a minute, because it’s now time for…
3. Model
The Model component is perhaps the easiest component to understand, because it’s often simply the data structures used by your app. The model could be nothing more than a class or two containing various fields: customer name, average income, likelihood they would want to be your friend, minimum distance in current court-ordered restraining order and so on.
If your program is more complicated that simply storing, displaying and editing data, you could also keep your ‘logic’ here. This would be the methods which process the data in some way.
Practical advice on creating an MVVM based
Now for the source code! When writing an app based on the MVVM model, you can just start as you normally would and design your model component, and knock up a few pages in XAML or even Blend. However, try to avoid adding any click handlers.
For each XAML page you create, create a new class to contain the View Model. You will need to instantiate this class in your XAML’s code behind.
For example, if you create a blank C# Windows Store App project you will be given a MainPage.xaml and MainPage.xaml.cs files. You should then create a MainPageViewModel.cs class, and instantiate it inside MainPage.cs, like this:
namespace MyMVVMApp
{
public sealed partial class MainPage : Page
{
private MainPageViewModel mainPageViewModel = new MainPageViewModel();
public MainPageViewModel MainPageViewModel
{
get { return this.mainPageViewModel; }
}
public MainPage()
{
this.InitializeComponent();
}
}
}
Now to wire up some data, and add an event handler.
Accessing Data in the View Model
Let’s create a variable in the View Model, which will be data bound to a TextBlock in the XAML. We could define the type of the variable by accessing our classes in Model, but for now, let’s just use a simple string.
First of all though, we need to make sure the XAML in MainPage.xaml knows where to look for data bound sources. Add the following line to the <Page> section right at the top of the file:
DataContext="{Binding MainPageViewModel, RelativeSource={RelativeSource Self}}"
Now we can define the TextBox control in the same XAML file too:
<TextBox Text="{Binding stringData, Mode=TwoWay}" VerticalAlignment="Top" Margin="20,20,10,0" />
Notice the data binding to the variable called stringData is TwoWay in this case. This means that not only will the TextBox take its value from our bound variable, but it will also change the variable if the user edits it in the TextBox.
We must of course create the stringData variable, and we do that in MainPageViewModel.cs, like this:
public class MainPageViewModel
{
public string data = "Testing one two three";
public string stringData
{
get
{
return data;
}
set
{
data = value;
}
}
…
}
And if you build and run this, you’ll see that the TextBox displays the text you would expect it to display. Editing the contents of the TextBox changes the variable, which you can check if you add breakpoint somewhere and use the debugger. But let’s add a button to make that easier, and also to demonstrate how to data bind a button event, because data binding an event seems a crazy thing to be able to do.
When adding Button controls to XAML, you’ll have used the Click=”” event handler, I’m sure. However, our goal is to avoid linking the XAML directly to the code behind page, so let’s try something else. Declare your button in the MainPage.xaml file like this:
<Button Content="Button" Command="{Binding ClickOne}" />
Interesting, huh? We are using something called Command to bind an event handler. How is this going to work? Can you simply place a method called ClickOne() into the MainPageViewModel.cs file? Sadly not – there’s a little more to it.
Let’s cheat a little, and use some already written code contained in RelayCommand.cs class. This class will be created if you create a new C# project which uses Navigation (so not the Blank project).
- Create a new C# project that uses Navigation, such as the Hub template.
- Find the Common folder in the Solution Explorer.
- Find the RelayCommand.cs class.
- Add this class to your own project.
This class is a useful lump of code which will simplify redirecting events to your View Model class. Use it by adding the following code to your MainPageViewModel.cs file:
public RelayCommand ClickButton { get; private set; }
public MainPageViewModel()
{
ClickButton = new RelayCommand(() => Click());
}
private void Click()
{
System.Diagnostics.Debug.WriteLine(stringData);
}
We end up with a new event handler method, Click(), which just for kicks which ask to output the current contents of the stringData variable. This proves that not only is the event handler wired up properly, but also that the stringData is bound in TwoWay mode.
Hurrah! We’ve successfully separated the XAML and its code behind page, from our View Model page. As a result, we can hand off the XAML to our designer buddy to work on, while we write unit tests around the View Model code. We could even write an entirely different XAML View, perhaps for Windows Phone, and keep the same View Model class without changing a line of code. Good work, us!
Conclusion
Although we’ve done some clever stuff there, you might think that working with an MVVM model is just not worthwhile for your projects, and might introduce extra complexity and weird and forced code contortions. And simply because your app is an action game or something smaller than a warehouse business database client, it's not worth the hassle. I’m not going to argue with you: IMHO it is a design pattern that grew out of Enterprise-class Windows apps that talk to databases or web services and display lots of forms and text on-screen in boring columns.
However, you should be able to see how separating the user interface code from the code that makes decisions / queries the web / generates fractals / does whatever your app does, has many benefits. How nice it would be to hand the entire UI to someone else to beautify, and know it’ll still integrate perfectly into the rest of the project when you get it back. Even for smaller apps, keeping your code arranged by function, rather than stuffed into a single class, pays off when it comes to debugging, testing and re-use.
I guess my point is that you shouldn't write it off as not relevant to your apps. I hope this brief introduction has be useful and understandable. Next time you select File / New / Project from your Visual Studio menu, have a think how using a design pattern might help you.
See Also
I found a lot of useful information on design patterns and MVVM on MSDN, including:
Robert Green's excellent Channel 9 video which made it clear for me
Robert's associated blog and sample code.
MVVM from the Patterns and Practices Group