SyntaxHighlighter

Monday, February 28, 2011

WPF using only F# and Xaml Part 1

In my early days of researching F# I spent quite a bit of time looking for code to read or download.
Early on I came across two really clean ways of interacting with Xaml from F#. The first and simplest way
is what I'll focus on in this post. So first things first - lets fire up VS2010 or VS2008 and create a new F# project. I started with the WPF template which is available in the VS gallery in VS2010, but if you don't have the template it's no big deal. Just create an F# console application and under the project type change it to windows application and you should be good to go.




Next thing you want to do is add a new item to the project. You will not see an option to add a .xaml file
so you will have to type it in. For the sake of this blog post just name the item MainView.xaml and add to the project.
Initially, visual studio knows about the xaml file so it tries to display the designer. The problem you'll see
is the designer shows warnings, which basically means that their is no xaml to display. So at this point all you need to do is copy and paste either a block of xaml which represents a window or a user control.
For this post I'll use some xaml that I generated from expression blend 4. 

 
You'll notice in the circled area that there is no x:Class attribute which indicates the code behind file.
This removes some complexity with getting F# to see the block of xaml. I'll cover that in part 2.
The next part is to right click on the xaml file in the project and click on Properties set two properties on the file itself.

1) Set  Build Action = None
2) Copy to output directory = Copy if newer

Now we should be ready to add the necessary assemblies to the project and starting writing some code.
The assemblies that you'll need are the follow...
- PresentationCore
- PresentationFramework
- System
- System.Xaml
- System.Xml
- UIAutomationTypes
- WindowsBase

Now the code... in the program.fs file just add the following code below.

open System
open System.IO
open System.Windows
open System.Windows.Controls
open System.Windows.Markup

(* Special thanks to Luke Hoban for providing the twitter app sample (From TechEd 2010)
   which demonstrates this technique *)
(* http://blogs.msdn.com/b/lukeh/ *)

//the tick marks are just for this blog post (do not include these in the actual code) :-)
['<'STAThread'>'] 
do() 

let window = XamlReader.Load(File.OpenRead("MainView.xaml")) :?> Window

(* Hook into xaml elements here *)
let why = window.FindName("Why") :?> Button
let answer = window.FindName("answer") :?> TextBlock
(* Handle click event on Why button *)
do why.Click.Add( fun _ -> answer.Text <- "Because F# works with Xaml!!" )

ignore <| (new Application()).Run window

That's essentially all that is needed to code an even quicker wpf application in F#. Again, this is not the only
way to do this but it is a simple and clean way to do it for a quick view or app.

Until next time...
-Develop with passion


2 comments:

  1. Why not simply create a separate project of type "WPF User Control Library" and put all your XAML in there? Then you don't have to muck around with getting XAML files to behave in an F# project. Sure, there'll be .cs code-behind files generated for your views, but there shouldn't be code in code-behind anyway.

    Just my $0.02 :)
    OJ

    ReplyDelete
  2. OJ - I definitely agree with your comment if the scenario is just XAML. If you're authoring a custom widget or control which has a lot of custom behavior/animations to make it a unique experience and you want to use F# to code it up, then I'd lean more towards this approach. I also agree with you (to a point) when you say that there should not be code in the code behind. I think there should be an exception to this when you have view specific code... for example custom animations that require to much over head to execute in XAML.

    ReplyDelete