Sunday, November 30, 2014

Evolution of the F# Empty WPF Template

Back in March 2012, I announced that the F# Empty WPF project template had been enhanced to include a type provider from the FSharpx type providers collection. Today, another evolution of the F# Empty WPF template has occurred. The FSharpx.TypeProviders.Xaml type provider has been replaced with Reed Copsey's FsXaml for WPF type provider.

Building a Simple Example:

It's very easy to get started with the latest version of the template as well as FsXaml. Here the steps to create an overly simple example with the new version of the template, FxXaml and FSharp.ViewModule.Core (which is also inclueded in the template):

1. Create a new project with the latest version of the F# Empty Windows App (WPF) template.
2. Build the project and Enable the type provider when requested to do so. You can now run the project, which at this point simply displays a blank screen.
3. Open the MainWindow.xaml.fs file and replace the contents with the following:

namespace ViewModels
open System
open System.Windows
open FSharp.ViewModule
open FSharp.ViewModule.Validation
open FsXaml
type MainView = XAML<"MainWindow.xaml", true>
type MainViewModel() as self =
inherit ViewModelBase()
let name = self.Factory.Backing(<@ self.Name @>, "")
let display = self.Factory.Backing(<@ self.Display @>, "")
let goCommand = self.Factory.CommandSyncParam(fun param -> self.Display <- sprintf "Your Name Is: %s" param)
member x.Name with get() = name.Value and set value = name.Value <- value
member x.Display with get() = display.Value and set value = display.Value <- value
member x.GoCommand = goCommand
view raw gistfile1.fs hosted with ❤ by GitHub

4. Open the MainWindow.xaml file add the following to the Grid element:

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Text="Enter Your Name:" FontSize="16" Grid.Row="0" Grid.ColumnSpan="2" />
<TextBox Margin="5" Grid.Row="1" Grid.Column="0" FontSize="16" Text="{Binding Name}"/>
<Button Margin="3" Grid.Row="1" Grid.Column="1" FontSize="16" Content="Go"
Command="{Binding GoCommand}" CommandParameter="{Binding Name}"/>
<Label Foreground="Gray" Margin="5" Grid.ColumnSpan="2" Grid.Row="2"
FontSize="16" Content="{Binding Display, Mode=OneWay}"/>
view raw FsXamlExXaml.fs hosted with ❤ by GitHub

After this change, the MainWindow.xaml file will look something like the following with one small different depending on what you named your project:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewModels;assembly=FsEmptyWindowsApp1"
xmlns:fsxaml="http://github.com/fsprojects/FsXaml"
Title="MVVM and XAML Type provider" Height="200" Width="400">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="5" Text="Enter Your Name:" FontSize="16" Grid.Row="0" Grid.ColumnSpan="2" />
<TextBox Margin="5" Grid.Row="1" Grid.Column="0" FontSize="16" Text="{Binding Name}"/>
<Button Margin="3" Grid.Row="1" Grid.Column="1" FontSize="16" Content="Go" Command="{Binding GoCommand}" CommandParameter="{Binding Name}"/>
<Label Foreground="Gray" Margin="5" Grid.ColumnSpan="2" Grid.Row="2" FontSize="16" Content="{Binding Display, Mode=OneWay}"/>
</Grid>
</Window>
view raw gistfile1.xml hosted with ❤ by GitHub

For additional examples checkout the demos in the FsXaml GitHub repo.