SyntaxHighlighter

Monday, February 28, 2011

WPF using only F# and Xaml Part 2

This final part of the 2 parts is to try to show how to get all the benefits of Part 1 with out deploying the xaml file along with the binaries.

There are two main things that you need to change.

1) Build Action & Copy to Output Directory
Build Action = Resource
Copy to Output Directory = Do not copy

2) Is of course the code in program.fs.


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


//again do not include the tick marks below in sta-thread attribute.
['<'STAThread'>']
do()

let uri = new System.Uri("/WPF_with_Xaml;component/MainView.xaml", UriKind.Relative)
let window =  Application.LoadComponent(uri) :?> 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


A few things to note when implementing this way.
1) The performance is much slower because the framework has to convert the xaml to baml first.
One way around that would be to obviously have the baml ready to go.
2) If the slightly slow startup is not an issue for you then you get the added benefit of not having to deploy
the xaml file. :-)


Until next time...
Develop with passion

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