MVVM with F# (Tutorial)

Intro

I have reason to believe that F# will be the language of choice in several years for the .NET platform. This language was designed to assist error-prone developers such as myself from making mistakes that stem from having to write too many lines of code for expressing how a moderate operation is to execute. F# reduces the lines of code required by providing default constructs that supports cleaner and more concise code. As a result, in order to stay current, I have decided to go full throttle into learning this mysterious programming language.

The following tutorial details how to implement MVVM with F#.

Solution Explorer

To start off, let’s create two projects. Our first project will be a WPF project. Our other project will be a project to hold our viewmodel.

1. Create a WPF project.
2. Create a Portable Class Library

3. Add a ViewModelBase and a ViewModel file to the PCL (aka: Model)

NOTE:

The WPF project will contain our view and the PCL will contain our viewmodel.

Mine looks like the following (fully implemented):FSharpMVVM

ViewModelBase

We will first flush out our model project. To so, let’s first establish some reusable plumbing by establishing our base class for our deriving viewmodels to leverage.

The code below will provide our base behavior for sending a property change notification to an observer (i.e. a databound view):

namespace Model

open System.ComponentModel
open Microsoft.FSharp.Quotations.Patterns

type ViewModel () =
    let propertyChanged = 
        Event<PropertyChangedEventHandler,PropertyChangedEventArgs>()
    let getPropertyName = function 
        | PropertyGet(_,pi,_) -> pi.Name
        | _ -> invalidOp "Expecting property getter expression"
    interface INotifyPropertyChanged with
        [<CLIEvent>]
        member this.PropertyChanged = propertyChanged.Publish
    member private this.NotifyPropertyChanged propertyName = 
        propertyChanged.Trigger(this,PropertyChangedEventArgs(propertyName))
    member this.NotifyPropertyChanged quotation = 
        quotation |> getPropertyName |> this.NotifyPropertyChanged

Observe that the code above provides an interface which manages quotations so that a property name does not have to be hardcoded by hand. Hence this technique supports better maintainability in regards to future refactoring tools.

ViewModel

Now let’s implement our viewmodel. In our viewmodel, we will derive from our base class (i.e. ViewModelBase) to ensure that we trigger property change notification. Note that for our property setters we invoke the NotifyPropertyChange function on our base class. F# does not support the “protected” access modifier. As a result, we explicity call our base function and supply a refactor-friendly argument.

namespace Model
type ViewModel() =
    inherit ViewModel()
    let mutable firstName = ""
    let mutable lastName = ""

    member this.FirstName
        with get() = firstName 
        and set(value) =
            firstName <- value
            base.notifyPropertyChanged(<@ this.FirstName @>)

    member this.LastName
        with get() = lastName 
        and set(value) =
            lastName <- value
            base.notifyPropertyChanged(<@ this.LastName @>)

    member this.GetFullName() = 
        sprintf "%s %s" (this.FirstName) (this.LastName)

View

Let’s implement our view. In our view, we do NOT use a “class” attribute for our Window element. The class attribute supports code-behind ceremony that C# enables. Instead, for F# applications, we can just ensure that we do not include the class element. In addition, we add a TextBlock control and bind it to a property on our viewmodel.

<Window
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"
xmlns:model="clr-namespace:Model;assembly=Model"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">

<Window.DataContext>
<model:ViewModel />
</Window.DataContext>

<Grid>
<TextBlock Text="{Binding FirstName}" />
</Grid>
</Window>

When and if you wire this up correctly and run the application, you should end up with the following results:

FSharpMVVM._Runtime

Conclusion

In conclusion, I have reason to believe that F# will be the language of choice in several years for the .NET platform. This language was designed to assist error-prone developers such as myself from making mistakes that stem from having to write too many lines of code for expressing how a moderate operation is to execute. F# reduces the lines of code required by providing default constructs that supports cleaner and more concise code. As a result, in order to stay current, I have decided to go full throttle into learning this mysterious programming language and provided a tutorial to get readers up and running.

Leave a comment