Quickstart WPF F#-only app in VSCode - Part 2
The first part shown how to create a WPF F# project with simple window and its view model, build this project and run it.
Now lets add FsXaml using packet, use it to create types from XAML and create user control. All by directly modifying project files and run commands from the VS Code terminal.
paket
is a nice alternative to nuget
. Its executable can be downloaded from the paket's project repository on GitHub (see this link. paket.exe
should be placed into the project's folder or in one of the folders listed in the PATH environment variable in order to be accessible from the terminal.
Make the initial paket files, including empty paket.dependencies
:
PS C:\...\WPFFSharpQuickStart> ./paket init
Install FsXaml for WPF and add reference:
PS C:\...\WPFFSharpQuickStart> ./paket add FsXaml.Wpf --version 3.1.6 --project MyApp\MyApp.fsproj
The FsXaml wants FSharp.Core 4.3 but the project references FSharp.Core 4.4 so the MSBuild complains a bit about it. It can be fixed by adding the following mapping to the App.config
's configuration
node:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core"
publicKeyToken="b03f5f7f11d50a3a"
culture="neutral"/>
<bindingRedirect oldVersion="4.3.0.0"
newVersion="4.4.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
After FsXaml is installed, loading and instantiating XAML components and user controls become much simpler. For example, the Program.fs
becomes
open System
open FsXaml
type App = XAML<"App.xaml">
[<STAThread>]
[<EntryPoint>]
let main (_) =
let application = App()
application.Run () |> ignore
0
Although it works perfectly now, it is better to define XAML-based types in the special Controls.fs
file in the application's namespace:
Controls.fs
namespace MyApp
open FsXaml
type App = XAML<"App.xaml">
Include it to the project:
MyApp.fsproj
<Compile Include="MainViewModel.fs" />
+ <Compile Include="Controls.fs" />
<Compile Include="Program.fs" />
and modify the entry point file:
Program.fs
open System
open MyApp
[<STAThread>]
[<EntryPoint>]
let main (_) =
let application = App()
application.Run () |> ignore
0
FsXaml greatly simplifies creating of user controls:
Welcome.xaml
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Border BorderBrush="{x:Null}"
Height="50">
<TextBlock Text="{Binding WelcomeText}"
VerticalAlignment="Stretch"
TextAlignment="Center"
FontFamily="Segoe"
FontSize="26" />
</Border>
</UserControl>
WelcomeViewModel.fs
namespace MyApp
open MyApp.Library
type WelcomeViewModel () =
let welcomeTextProvider = WelcomeTextProvider ()
member vm.WelcomeText
with get() = welcomeTextProvider.GetWelcomeText ()```
MyApp.fsproj
...
<Compile Include="AssemblyInfo.fs" />
+ <Resource Include="Welcome.xaml" />
+ <Compile Include="WelcomeViewModel.fs" />
<Resource Include="MainWindow.xaml" />
...
Controls.fs
...
type App = XAML<"App.xaml">
type Welcome = XAML<"Welcome.xaml">
MainWindow.xaml
...
</Window.DataContext>
<Grid>
<local:Welcome DataContext="{Binding Welcome}">
</Grid>
...
And that's it. Now build and run, everything should work.
You can get the version of the WPFFSharpQuickStart project with paket and FsXaml by getting the fsxaml branch:
C:\...> git clone -b fsxaml https://github.com/AlexAtNet/WPFFSharpQuickStart