Click here to Skip to main content
15,892,059 members
Articles / Operating Systems / Windows Phone

Windows Phone TDD Part 4: The Proper Way To Do MVVM

Rate me:
Please Sign up or sign in to vote.
4.50/5 (5 votes)
24 Feb 2014CPOL3 min read 14.7K   1   5
Windows Phone TDD Part 4: The proper way to do MVVM

A few days ago, a friend asked me if you should put the business logic in the Models and the ViewModels from MVVM. Basically, my answer was NO, HELL NO!

I will talk about just two of the reasons why I think this.

The first one is that you will have to rewrite your business logic for every app where you will use it. Let’s say that you have a client that wants an app for handling his account, so you make him a desktop app with WPF. You use MVVM, and you have your logic there, but what do you do when the client wants a Windows Phone app? The logic is in the ViewModels from the WPF app, so now you have to rewrite it again for the Windows Phone app. Wouldn’t it be better if the business logic was in some Portable Class Library that you could reuse for every platform instead of binding it with the ViewModels? I thought so.

The second reason is that I think the ViewModels should handle some of the UI logic as well. If you’re doing TDD, then you will want to test as much of your code as possible. If the ViewModels don’t contain the business logic, what’s stopping you from using them to control your UI? Imagine the following scenario, you have an app that shows a popup with a login form. When the user clicks on the login button, and he is logged in, you want the popup to dissappear. The problem is that you don’t know if the login was successful or not, so you can’t just close the popup when the button was pressed. So how do you make the View wait for an answer from the ViewModel? Or better, how do you write the code for this task so you could test it?

If you’re using Caliburn.Micro, you could bind the Visibility property of the popup to a boolean property in the ViewModel. The code for the login function could be like this:

C#
public async Task Login(string username, string password)
{
    var loginResult = await LoginUser(username, password);
    if (loginResult)
        LoginPopupIsOpened = false;
    else MessageBox.Show("An error occurred");
}

Because the popup visibility is binded to our property, then when I will set it to false, the popup visibility will be set to Collapsed. The upside here is that I can write a test for this very easily.

C#
[Test]
public void successful_login_should_close_popup()
{
    var viewModel = new LoginViewModel();
    viewModel.LoginPopupIsOpened = true;
    BindAuthenticationServiceToSuccess(); //we bind the login function to return true
    await viewModel.Login();
    viewModel.LoginPopupIsOpened.Should().BeFalse();
}

If you want a high code coverage, try to make your ViewModel handle the UI, but don’t do it directly, so don’t use objects that are related to the UI (Button, Grid, TextBox, etc… or properties like Visibility, Text, etc.). You can see that I haven’t used the Visibility enum above, that’s because I want to keep the UI related stuff out of my ViewModel. So I’m binding Visibility to boolean properties, Image source Uri to string properties, events to functions, and so on. The rule is to keep all your functionality in the ViewModel, and the strictly UI stuff in the View. So far, this is working great for me, especially because I’m using Caliburn which makes the separation between the View and the ViewModel very easy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Feel IT
Romania Romania
Hey! I'm Bogdan Bujdea, a software developer from Romania. I started to learn programming since my first year of highschool with C++. During my time in college I tried various languages like Java, C#, Haskell, Javascript, Python, etc. but my favorite remains C#.
I started my career with Thinslices as a Windows 8 developer, but now I work for Feel IT Services as a Windows Phone developer.

Comments and Discussions

 
QuestionModel != ViewModel Pin
William E. Kempf6-Mar-14 7:16
William E. Kempf6-Mar-14 7:16 
AnswerRe: Model != ViewModel Pin
Bogdan Bujdea9-Mar-14 6:37
Bogdan Bujdea9-Mar-14 6:37 
GeneralRe: Model != ViewModel Pin
William E. Kempf10-Mar-14 7:49
William E. Kempf10-Mar-14 7:49 
GeneralRe: Model != ViewModel Pin
Bogdan Bujdea10-Mar-14 9:20
Bogdan Bujdea10-Mar-14 9:20 
GeneralRe: Model != ViewModel Pin
William E. Kempf10-Mar-14 9:46
William E. Kempf10-Mar-14 9:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.