September 2011

Volume 26 Number 09

F# Programming - Build MVVM Applications in F#

By Chris Marinos | September 2011

Despite being a newcomer to the Visual Studio family, F# has already helped many .NET developers discover the power of functional programming. F# has a strong, growing reputation for its ability to simplify complicated problems like parallel and asynchronous programming, data processing and financial modeling. However, that doesn’t mean that F# is a niche language; it’s also great for solving everyday problems.

In this article, you’ll learn how to use F# to build practical Silverlight and Windows Presentation Foundation (WPF) Model-View-ViewModel (MVVM) applications. You’ll see how the same concepts that make F# great for simplifying complicated algorithms can also be used to reduce the ceremony around your view models. You’ll also see how the well-publicized asynchronous workflows in F# can be applied in a GUI setting. Finally, I’ll cover two common approaches for structuring MVVM applications in F#, as well as the strengths and weaknesses of each approach. By the end of the article, you’ll understand that F# is more than just a tool for specialized problems, and you’ll be able to use F# to make even the simplest applications easier to read, write and maintain.

Reducing Ceremony

You might think F# is a strange language to use for working with GUI applications. After all, functional languages de-emphasize side effects, and frameworks like Silverlight and WPF are laden with side effects. Maybe you think that view models don’t contain enough complicated logic to see a benefit in switching to a functional style. Perhaps you believe that functional programming requires a paradigm shift that makes it difficult to work with design patterns like MVVM. The truth is that using F# to construct view models and models is just as easy as constructing them in C#. View models are also a great place to see how F# reduces ceremonious, boilerplate code. You may be surprised at how effectively F# improves the signal-to-noise ratio in your code if you’re used to C# programming.

Figure 1 contains F# code for a simple movie model with fields for a name, a genre and an optional rating. If you aren’t familiar with option types in F#, you can think of them as a more powerful and expressive analog to nullables in C#. An option type is a natural way to state that a movie model may or may not have a rating, but it can cause problems for data binding. For example, trying to get the value of an option type set to None (the equivalent of null for nullables) will throw an exception. You may also want to hide the control that’s bound to Rating if it’s set to None. Unfortunately, if WPF or Silverlight encounters an exception while trying to get the value of Rating, your visibility binding may not execute properly. This is a simple example of where you need a view model to add additional display logic around ratings.

Figure 1 A Simple Model for a Movie

type Movie = {
  Name: string
  Genre: string
  Rating: int option
}

Figure 2 shows a view model with an example of this additional display logic. If the rating is present, its value is passed to the view; otherwise the rating is given a default value of 0. This simple logic prevents exceptions from being raised when Rating is None. The view model also exposes a second property to handle the visibility binding. This method simply returns true if Rating is Some and false if it is None. The logic in this view model is simple, but the logic isn’t the point of the example. Instead, look at how concisely F# expresses the definition of the view model. In C#, view models often become inundated with boilerplate code that clutters the view logic just to make the compiler happy.

Figure 2 A View Model for a Movie with Display Logic for Ratings

type MovieViewModel(movie:Movie) =
  member this.Name = movie.Name
 
  member this.Genre = movie.Genre
 
  member this.Rating =
    match movie.Rating with
    | Some x -> x
    | None -> 0
 
  member this.HasRating = movie.Rating.IsSome

Figure 3 shows the same view model written in C#. The increase in ceremonious code is dramatic. It takes roughly four times as many lines of code to express the view model in C# as it does in F#. Much of that increase comes from curly braces, but even significant items like type annotations, return statements and accessibility modifiers get in the way of understanding the logic that the view model is built to encapsulate. F# reduces this noise and places the focus on the code that matters. Functional programming has a bad reputation at times for being overly terse and difficult to read, but in this example, it’s clear that F# doesn’t sacrifice clarity for brevity.

Figure 3 A C# View Model for Movies

class MovieViewModelCSharp
{
  Movie movie;
 
  public MovieViewModelCSharp(Movie movie)
  {
    this.movie = movie;
  }
 
  public string Name
  {
    get { return movie.Name; }
  }
 
  public string Genre
  {
    get { return movie.Genre; }
  }
 
  public int Rating
  {
    get
    {
      if(OptionModule.IsSome(movie.Rating))
      {
        return movie.Rating.Value;
      }
      else
      {
        return 0;
      }
    }
  }
 
  public bool HasRating
  {
    get
    {
      return OptionModule.IsSome(movie.Rating);
    }
  }
}

The preceding example shows one benefit that F# offers when writing view models, but F# also fixes another common problem with view models in MVVM applications. Say that your domain has changed and your model needs to be updated; Genre is now a list of tags instead of a single string. In the model code, that’s a one line change from this:

Genre: string

To this:

Genre: string list

However, because this property was communicated to the view through the view model, the return type on the view model also needs to change. This requires a manual change to the view model in C#, but it happens automatically in F# due to type inference. This may be surprising if you aren’t accustomed to type inference in F#, but it’s exactly the behavior you want. Genre doesn’t require any display logic, so the view model simply hands this field off to the view without modification. In other words, you don’t care about the return type of the property on the view model as long as it matches the return type of the property on the model. That’s exactly what the F# code states. Keep in mind that F# is still statically typed, so any misuse of the field on the view model or model (XAML aside) will be a compile error.

Leveraging Existing Assets

The view models in Figure 1 and Figure 2 supported only one-way binding because they were only responsible for adding display logic to the model. These simple view models are useful for demonstrating the ability of F# to reduce ceremonious code, but view models usually need to support two-way binding by implementing INotifyPropertyChanged for mutable properties. It’s common for C# MVVM applications to contain a view model base class to make implementing INotifyPropertyChanged and other view model concerns easier. You might be worried that you have to re-implement this behavior in F#, but F# allows you to reuse existing C# view model base classes without having to rewrite them.

Figure 4 shows the use of the ViewModelBase class in F#. ViewModelBase is a C# base class written by Brian Genisio (houseofbilz.com) that I like to use for all of my C# and F# view models. In Figure 4, the base class provides the base.Get and base.Set functions that are used to implement INotifyPropertyChange. ViewModelBase also supports convention-based command generation using the dynamic programming features of C#. Both of these features work seamlessly with an F# view model because F# was designed to easily interoperate with other .NET languages. Check out the source at viewmodelsupport.codeplex.com for more information on how to use ViewModelBase.

Figure 4 Inheriting from a C# ViewModelBase Class

type MainWindowViewModel() =
  inherit ViewModelBase()
 
  member this.Movies
    with get() =
      base.Get<ObservableCollection<MovieViewModel>>("Movies")
 
    and set(value) =
      base.Set("Movies", value)

Getting Asynchronous

Supporting asynchronous and cancelable operations is another common requirement for view models and models. Fulfilling this requirement using traditional techniques can add significant complexity to your application, but F# contains powerful asynchronous programming features to simplify this task. Figure 5 shows a synchronous call to a Web service to get movie data. The response from the server is parsed into a list of movie models. The models in this list are then projected into view models and added to an ObservableCollection. This collection is data-bound to a control on the view to display the results to the user.

Figure 5 A Sample Web Request for Processing Movies

member this.GetMovies() =
  this.Movies <- new ObservableCollection<MovieViewModel>()
 
  let response = webClient.DownloadString(movieDataUri)
 
  let movies = parseMovies response
 
  movies
  |> Seq.map (fun m -> new MovieViewModel(m))
  |> Seq.iter this.Movies.Add

Converting this code to run asynchronously would require a complete overhaul of the control flow using traditional asynchronous libraries. You’d have to break your code into separate callback methods for each asynchronous call. This adds complexity, makes the code more difficult to reason about and greatly increases the maintenance overhead of the code. The F# model doesn’t have these problems. In F#, you can implement asynchronous behavior by making a small set of changes that don’t impact the structure of the code, as Figure 6 shows.

Figure 6 An Asynchronous Web Request for Processing Movies

member this.GetMovies() =
  this.Movies <- new ObservableCollection<MovieViewModel>()
 
  let task = async {
    let! response = webClient.AsyncDownloadString(movieDataUri)
 
    let movies = parseMovies response
 
    movies
    |> Seq.map (fun m -> new MovieViewModel(m))
    |> Seq.iter this.Movies.Add
  }
 
  Async.StartImmediate(task)

The example in Figure 6 shows the same code running asynchronously. The code that calls the Web service and updates the result list is wrapped in an async block to start the change. The let! keyword is used inside this block to tell F# to run a statement asynchronously. In the example, let! tells the Web client to asynchronously make a Web request. F# provides the AsyncDownloadString method as an extension to WebClient to facilitate this process. The last change is the call to Async.StartImmediate, which starts the async block on the current thread. Running on the GUI thread avoids messy exceptions that happen if you try to update the GUI on a background thread, and the asynchronous behavior ensures that the GUI won’t get hung while a Web request occurs.

The change to run this behavior asynchronously didn’t require much additional code, but perhaps just as importantly, it didn’t require a change in the way the code was structured. When you write the code the first time, you don’t have to worry about designing it to possibly run asynchronously in the future. You’re free to write synchronous code when prototyping and then easily convert it to async when it becomes necessary. This flexibility can save you hours of development time and make your clients much happier when you’re able to respond to change more rapidly.

This style of asynchronous programming should look familiar if you’ve been keeping up with the latest developments in C#. That’s because the async updates that are coming to C# are heavily based on the F# model. Async in C# is available via a community technology preview (bit.ly/qqygW9), but the asynchronous features of F# are production-ready today. Asynchronous workflows have been available in F# since the language was released, so they’re an excellent example of why learning F# will make you a better C# developer.

Though the C# and F# models are similar, there are some differences, and cancellation is a major one. The code in Figure 7 adds cancellation to the GetMovies function. Again, this requires a very small change. To make the workflow support cancellation, you need to create a CancellationTokenSource and pass its cancellation token to the Async.StartImmediate function. Figure 7 includes some additional setup code at the top of the GetMovies function to cancel any outstanding operations to avoid updating the observable collection more than once. A new CancellationTokenSource is also issued with every call to the function to ensure that each run of the workflow has a unique CancellationToken.

Figure 7 Cancellation in F#

let mutable cancellationSource = new CancellationTokenSource()
 
member this.GetMovies() =
  this.Movies <- new ObservableCollection<MovieViewModel>()
  cancellationSource.Cancel()
  cancellationSource <- new CancellationTokenSource()
 
  let task = async {
    let! response = webClient.AsyncDownloadString(movieDataUri)
 
    let movies = parseMovies response
 
    movies
    |> Seq.map (fun m -> new MovieViewModel(m))
    |> Seq.iter this.Movies.Add
  }
 
  Async.StartImmediate(task, cancellationSource.Token)

In the C# model you have to manually pass a CancellationToken down the chain of function calls to support cancellation. This is an intrusive change that could potentially require you to add an extra argument to many function signatures. You also need to manually poll the CancellationToken to see if cancellation is requested. The F# model requires much less work. Whenever the asynchronous workflow encounters a let!, it will check the CancellationToken it received in the StartImmediate call. If that token is valid, the workflow will execute as usual. If the token is invalid, the operation won’t execute and the rest of the workflow won’t run. Implicit handling of cancellation is a nice feature, but you aren’t constrained to this. If you need to manually poll the CancellationToken for a workflow, you can access it with the Async.CancellationToken property:

let! token = Async.CancellationToken

Structuring MVVM Applications in F#

Now that you’ve seen a few practical ways that F# can enhance your view models and models, I’ll explain how to incorporate F# into your Silverlight and WPF applications. There are many different ways to structure your MVVM applications in C#, and the same is true in F#. I’ll cover two of these approaches in this article: the all-F# approach, and the polyglot approach that uses C# for views and F# for view models and models. I prefer the polyglot approach for a few reasons. First, it’s the approach recommend by the F# team. Second, tool support for WPF and Silverlight in C# is far more robust than it is for F#. Finally, this approach allows you to incorporate F# into existing applications and provides a low-risk way to try out F# in your MVVM applications.

The all-F# approach is nice because it allows you to write your application in one language, but it does come with some limitations. I’ll show you how to overcome a few of these common roadblocks a little later, but I find that the rewards aren’t worth the workarounds for anything but small applications. The polyglot approach does restrict you from using F# in your view code, but well-constructed MVVM applications should contain very limited amounts of view logic. Furthermore, C# is a great language for writing view logic when necessary because view logic tends to be side-effect-heavy and imperative in nature.

Using the Polyglot Approach

It’s very easy to create an MVVM application using the polyglot approach. First, create a new WPF project in C# using the WPF Application project template. This project is responsible for any views and codebehind you need for your application. Next, add a new F# library project to the solution to hold view models, models and any other non-view code. Finally, be sure to add a reference to the F# library project from the C# WPF project. This setup is all that’s required to get started with the polyglot approach.

F# is designed for smooth interop with any .NET language, so that means you can connect F# view models to C# views using any method you traditionally use for C# view models. I’ll show you an example that uses codebehind for simplicity’s sake. First, create a simple view model by renaming Module1.fs in the F# project to MainWindowViewModel.fs. Fill the view model with the code from Figure 8. Connect the F# view model to a C# view using the code from Figure 9. If you didn’t know that the view model was written in F#, you wouldn’t be able to tell the difference from a C# view model.

Figure 8 A Dummy F# View Model

namespace Core.ViewModels
 
type MainWindowViewModel() =
  member this.Text = "hello world!"
Figure 9 Connecting the F# View Model to the C# View
protected override void OnInitialized(EventArgs e)
{
  base.OnInitialized(e);
 
  this.DataContext = new MainWindowViewModel();
}

Figure 9 Connecting the F# View Model to the C# View

protected override void OnInitialized(EventArgs e)
{
  base.OnInitialized(e);
 
  this.DataContext = new MainWindowViewModel();
}

Add a text box to MainWindow.xaml and set the Binding to Text. Again, everything behaves just as if the application were written exclusively in C#. Make sure the binding works by running the application and viewing the standard “hello world!” greeting.

The All-F# Approach

As I mentioned earlier, I prefer the polyglot approach for its ease of use and flexibility. However, I’ll also discuss the all-F# approach to show you the tradeoffs. Visual Studio 2010 ships with a template for creating Silverlight libraries in F#, but it doesn’t include any templates for creating WPF or Silverlight applications in F#. Fortunately, there are several great online templates for this. I recommend starting with the templates created by Daniel Mohl (bloggemdano.blogspot.com), because they include sample applications you can use to see the structure of a full application. I’ll show you how to build a WPF F# application from scratch for the sake of learning, but I recommend using one of the online templates in practice.

Create a new F# application project called FSharpOnly to start with the all-F# approach. Wait for the project to finish being created, then open the project properties and change the output type to Windows Application. Now add references to PresentationCore, PresentationFramework, PresentationUI, System.Xaml and WindowsBase. Add files called App.xaml and MainWindow.xaml to the project and set the Build Action on each of these files to Resource. Note that by default there’s no item template in F# to generate XAML files, but you can use the general text document template with an extension of .xaml. Fill the XAML files with the code in Figure 10 and Figure 11, respectively. App.xaml and MainWindow.xaml perform the same functions that they do in a standard C# WPF application.

Figure 10 A Sample App.xaml File

<Application
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="assembly=FSharpOnly"
  StartupUri="MainWindow.xaml">
</Application>
Figure 11 A Sample MainWindow.xaml File
<Window
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="assembly=FSharpOnly"
  Title="Sample F# WPF Application Written Only in F#"
  Height="100"
  Width="100" >
  <Grid>
    <TextBlock>Hello World!</TextBlock>
  </Grid>
</Window>

Figure 11 A Sample MainWindow.xaml File

<Window
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="assembly=FSharpOnly"
  Title="Sample F# WPF Application Written Only in F#"
  Height="100"
  Width="100" >
  <Grid>
    <TextBlock>Hello World!</TextBlock>
  </Grid>
</Window>

Now add the code in Figure 12 to Program.fs. This code is responsible for loading the App.xaml file and running the application.

Figure 12 A Sample Program.fs

open System
open System.Windows
open System.Windows.Controls
open System.Windows.Markup
 
[<STAThread>]
[<EntryPoint>]
let main(_) =
  let application = Application.LoadComponent(new Uri("App.xaml", UriKind.Relative)) :?> Application
  application.Run()

Run the application to get the “Hello World!” greeting. At this point you’re free to adopt whatever technique you prefer for wiring your view models to your models, just as you were with the polyglot approach.

One problem you may encounter with the all-F# approach involves static resources. App.xaml is normally defined as an ApplicationDefinition in C# WPF projects, but it’s defined as a Resource in the all-F# approach. This causes the resolution of static resources defined in App.xaml to fail at run time when you consume them from other XAML files. The workaround is simple: Change the Build Action of the App.xaml file to ApplicationDefinition and reload the designer. This will cause the designer to recognize resources in the App.xaml and load your views properly. Don’t forget to change App.xaml back to a Resource when you want to build the application, or you’ll get a build error.

Codebehind also works differently in the all-F# approach. F# doesn’t support partial classes, so XAML files can’t be associated with an .fs codebehind file like they can in C#. It’s good practice to avoid codebehind whenever possible in MVVM applications, but sometimes codebehind is the most practical way to solve a problem. There are a couple of ways you can work around the lack of traditional codebehind in F#. The most straightforward way is to simply construct your entire view in F#. Although this approach is straightforward, it can also be cumbersome because you lose the declarative nature of XAML. The other approach is to hook into your visual elements when the application is constructed. Figure 13 shows an example of this approach.

Figure 13 Main.fs Modified to Hook into UI Elements

let initialize (mainWindow:Window) =
  let button = mainWindow.FindName("SampleButton") :?> Button
  let text = mainWindow.FindName("SampleText") :?> TextBlock
 
  button.Click
  |> Event.add (fun _ -> text.Text <- "I've been clicked!")
 
[<STAThread>]
[<EntryPoint>]
let main(_) =
  let application = Application.LoadComponent(new Uri("App.xaml", UriKind.Relative)) :?> Application
 
  // Hook into UI elements here
  application.Activated
  |> Event.add (fun _ -> initialize application.MainWindow)
 
  application.Run()

The lack of partial classes in F# also makes it difficult to consume user controls. It’s easy to create user controls in XAML, but you can’t reference the user controls in other XAML files because there’s no partial class definition in the assembly. You can work around this by creating a XamlLoader class, as shown in Figure 14.

Figure 14 A XamlLoader Class for Creating User Controls in F#

type XamlLoader() =
  inherit UserControl()
 
  static let OnXamlPathChanged(d:DependencyObject) (e:DependencyPropertyChangedEventArgs) =
    let x = e.NewValue :?> string
    let control = d :?> XamlLoader
 
    let stream = Application.GetResourceStream(new Uri(x, UriKind.Relative)).Stream
    let children = XamlReader.Load(stream)
    control.AddChild(children)
 
  static let XamlPathProperty =
    DependencyProperty.Register("XamlPath", typeof<string>, typeof<XamlLoader>, new PropertyMetadata(new PropertyChangedCallback(OnXamlPathChanged)))
 
  member this.XamlPath
    with get() =
      this.GetValue(XamlPathProperty) :?> string
           
    and  set(x:string) =
      this.SetValue(XamlPathProperty, x)
 
  member this.AddChild child =
    base.AddChild(child)

This class lets you set the path to a XAML file using a dependency property. When you set this property, the loader parses the XAML from the file and adds the controls defined in the file as children of itself. In XAML, this is used as follows:

<local:XamlLoader XamlPath="UserControl.xaml" />

The XamlLoader workaround enables you to create user controls without reverting to the polyglot approach, but it’s one more obstacle you don’t have when creating views in C#.

Closing Thoughts

Now that you’ve seen F# in action, it’s clear that it’s a language for writing practical applications. You saw that F# reduces the ceremony in your code, making it easier to read and maintain your view models and models. You learned how to use features like asynchronous programming to solve complicated problems quickly and flexibly. Finally, I showed you an overview of two major ways to structure MVVM applications in F#—and the tradeoffs you experience with each approach. Now you’re ready to unleash the power of functional programming in your Silverlight and WPF applications.

The next time you write a Silverlight or WPF application, try writing it in F#. Consider writing portions of an existing application in F# using the polyglot approach. You’ll quickly see a drastic reduction in the amount of code you have to write and maintain. Roll up your sleeves and get your hands dirty with the all-F# approach; you’ll definitely learn something you didn’t know about WPF, Silverlight or F#. No matter what step you take next, once you experience the joy of programming in F#, you won’t be able to look at C# the same way.


Chris Marinos is a software consultant and Microsoft MVP focusing in F#. He works at SRT Solutions in Ann Arbor, Mich., and is enthusiastic about F# and functional programming. You can hear him speak about these and other interesting topics around the Ann Arbor area or by visiting his blog at chrismarinos.com.

Thanks to the following technical experts for reviewing this article: Cameron Frederick and Daniel Mohl