Yippy – the F# MVVM Pattern
- by MarkPearl
I did a recent post on implementing WPF with F#. Today I would like to expand on this posting to give a simple implementation of the MVVM pattern in F#. A good read about this topic can also be found on Dean Chalk’s blog although my example of the pattern is possibly simpler. With the MVVM pattern one typically has 3 segments, the view, viewmodel and model. With the beauty of WPF binding one is able to link the state based viewmodel to the view. In my implementation I have kept the same principles. I have a view (MainView.xaml), and and a ViewModel (MainViewModel.fs). What I would really like to illustrate in this posting is the binding between the View and the ViewModel so I am going to jump to that… In Program.fs I have the following code… module Program
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Markup
open myViewModels
// Create the View and bind it to the View Model
let myView = Application.LoadComponent(new System.Uri("/FSharpWPF;component/MainView.xaml", System.UriKind.Relative)) :?> Window
myView.DataContext <- new MainViewModel() :> obj
// Application Entry point
[<STAThread>]
[<EntryPoint>]
let main(_) = (new Application()).Run(myView)
You can see that I have simply created the view (myView) and then created an instance of my viewmodel (MainViewModel) and then bound it to the data context with the code…
myView.DataContext <-
new MainViewModel() :> obj
If I have a look at my viewmodel (MainViewModel) it looks like this…
module myViewModels
open System
open System.Windows
open System.Windows.Input
open System.ComponentModel
open ViewModelBase
type MainViewModel() =
// private variables
let mutable _title = "Bound Data to Textbox"
// public properties
member x.Title
with get() =
_title
and set(v) =
_title <- v
// public commands
member x.MyCommand =
new FuncCommand
(
(fun d -> true),
(fun e -> x.ShowMessage)
)
// public methods
member public x.ShowMessage =
let msg = MessageBox.Show(x.Title)
()
I have exposed a few things, namely a property called Title that is mutable, a command and a method called ShowMessage that simply pops up a message box when called.
If I then look at my view which I have created in xaml (MainView.xaml) it looks as follows…
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="F# WPF MVVM" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Path=Title, Mode=TwoWay}" Grid.Row="0"/>
<Button Command="{Binding MyCommand}" Grid.Row="1">
<TextBlock Text="Click Me"/>
</Button>
</Grid>
</Window>
It is also very simple. It has a button that’s command is bound to the MyCommand and a textbox that has its text bound to the Title property.
One other module that I have created is my ViewModelBase. Right now it is used to store my commanding function but I would look to expand on it at a later stage to implement other commonly used functions…
module ViewModelBase
open System
open System.Windows
open System.Windows.Input
open System.ComponentModel
type FuncCommand (canExec:(obj -> bool),doExec:(obj -> unit)) =
let cecEvent = new DelegateEvent<EventHandler>()
interface ICommand with
[<CLIEvent>]
member x.CanExecuteChanged = cecEvent.Publish
member x.CanExecute arg = canExec(arg)
member x.Execute arg = doExec(arg)
Put this all together and you have a basic project that implements the MVVM pattern in F#.
For me this is quite exciting as it turned out to be a lot simpler to do than I originally thought possible. Also because I have my view in XAML I can use the XAML designer to design forms in F# which I believe is a much cleaner way to go rather than implementing it all in code. Finally if I look at my viewmodel code, it is actually quite clean and compact…