F# Xaml application - MVVM vs MVC

Mon Apr 27 2015

Most popular approach for creating Xaml applications is MVVM - Model View ViewModel. But there is an alternative - MVC (Model View Controller). So what are advantages of using one or another in your F# projects?

Introduction

I am mainly Web developer and haven't created much desktop applications. I started some toy project and wanted to try creating desktop application in WPF. I wanted to follow best practices and started to look what approaches are used to build Xaml apps. Most common choice is MVVM, but recently I was reading the book F# Deep Dives where Dmitry Morozov described MVC. Thanks to the FsXaml type provider implementing both approaches now is really easy.

Sample project described in this article is simple game score board. You can increase/decrease score for each team and reset score to zero when starting new game.

Project template also installs few NuGet packages which will help you to work with Xaml and ViewModel for MVVM.

Now you can start building your application. First of all let's create Xaml view for our application. The view will be same for both MVVM and MVC application with minimal differences. It should display score for both teams, there should be the buttons to increase and decrease (to fix mistaken increase) score and there should be the button to start new game.

Next in view model create mutable field to store current score value and initialize it with default value. Also create two backing fields and member properties which uses these backing fields. Backing fields are created using FSharp.ViewModule factory.

Bind those properties in Xaml view to labels. Those should be bound to label's Content attribute.

<Label Content="{Binding ScoreA}"></Label>

Now it's time for behavior. Create functions for score property update, increase/decrease of score for each team and creating new game. Score property update function - updateScore, just sets and formats property values from current score.

All these actions should be bound to buttons on Xaml view and also each action should update score labels. It would be possible to call updateScore function in each previously created functions after state gets mutated, but there is also more functional way. State mutation functions returns unit and updateScore function has unit as input parameter, so those can be composed like:

let newIncA = incA >> updateScore

Then I created helper function to compose all defined functions with updateScore function and pattern match on resulting tuple to extract new composed functions.

Probably manually composing each new function would be easier, but this was good excercise to do :).

Now create view model methods for each command using FSharp.ViewModule factory. I am creating sync version of commands, but it is possible to use also async version, only then backing functions should also be async.

Bind these commands to Xaml view like in code below. Commands are bound to Command attribute.

<Button Command="{Binding NewGame}"></Button>

Pros

MVVM pattern looks quite simple in this application. It is also popular in WPF community. It is command driven and supports two way binding.

Cons

UI logic and view model is coupled in one view model class. It is not event-driven by default.

MVC

Start MVC project with same view as MVVM, but without any binding attributes for controls. Instead add name for each control wich has to be updated or which will trigger some event. For example, label code below.

<Label x:Name="ScoreALabel"></Label>

Next in MainWindow.xaml.fs create model, view and controller. All should inherit from FSharp.Desktop.UI base classes.

Model should be abstract class, so should add AbstractClass attribute and all it's properties should be abstract too. Score board's model will keep two values for score of teams A and B.

Now it's time to define view and it's events. Events are just discriminated union of all possible events we would want to handle. For game score board those are increasing/decreasing score for each team and creating new game.

In this example I have only buttons and only Click event for each. So the easiest way is to create list of button/model event tuples and then map each click event of the button to matching model event. Then use yield! to return stream of events.

Next bind model to label controls by overriding SetBindings method. SetBindings method has model as a parameter. Binding is defined using Binding class method OfExpression and providing it expression with binding between controls' properties and model properties.

Here I used helper function - scoreFormat to format model values as numbers with two digits. As label's attribute Content is of type obj, then I had to cast result of formatted string to obj too.

Now define controller. It should implement interface - IController by providing model and model's events. There are two methods to implement - InitModel where we set initial model values and Dispatcher witch maps events with event handlers. In this example event handlers are just methods of controller class. To map events with these methods Sync function is used.

The last step is to wire model, view and controller together and it is done in App.fs. I have to instantiate model, view (by providing instance of the window) and controller and then instantiate MVC class and start the application.

Pros

I like that MVC version uses event streams and that it separates data binding from UI logic.

Cons

While it provides event streams there is no way to manipulate the event stream based on current view model values (at least I couldn't find a way). I also do not like mutable model, but as I understand we have to live with it also in MVVM version. It also has lot more gluing code to write than MVVM version.

Summary

Both approaches seems to have diffrenet usages. MVC style application is more event driven, so it would fit more for applications which produces lot of events. On the other side MVVM style application is more data driven and would fit more for applications with lot of data forms and simple commands.

But I feel that non of these Xaml application styles benefit much from functional programming. I imagine that ideal application should consist of the view which produces events and event holds current view state. All application logic should be handled by filtering and manipulating events and view model, and in the output it should produce new view model which is bound back to the view. For now I haven't discovered such solution.

Hi! I'm Māris Krivtežs. I am Web developer primarily working with ASP.NET, EPiServer and front-end development at Geta, but same time learning different programming languages, learning new programming paradigms, architectures, and design. I spend my free time with my family, reading books, bicycling and traveling.