Thursday, November 20, 2008

F# and Silverlight 2.0

One of the appeal of learning WPF is that now I can leverage what I learned in WPF and apply them to building web applications via Silverlight 2.0. This blog talks about setting up a very simple Silverlight 2.0 web application with F#.

Since my laptop is running Windows XP, I needed to build an environment with which I can host my Silverlight application. I decided to build a Virtual PC environment running Windows Server 2008. I'm using F# version 1.9.6.2 to build this sample Silverlight application.

Below is the simple Silverlight application with only a single clickable button:


#light
namespace SilverLightFSharp
open System
open System.Windows
open System.Windows.Controls

type MyPage = class
inherit UserControl

new () as this = {} then
// Add button and do something with it...
let btn = new Button(HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center)
btn.Content <- "Click me"
btn.Click.Add(fun _ ->
btn.Content <- "The button has been clicked!")
this.Content <- btn

end

type MyApp = class
inherit Application

new () as this = {} then
this.Startup.Add(fun _ -> this.RootVisual <- new MyPage())
//base.Exit.Add( fun _ -> ()) //this.Application_Exit)
//this.InitializeComponent()

end

I also needed some scaffolding in order to get this Silverlight application to run. One of the scaffolding pieces I need is the AppManifest.xaml file. Below is the content of that AppManifest.xml file with the EntryPointAssembly and EntryPointType attributes set to my F# code.


<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
EntryPointAssembly="SilverLightFSharp"
EntryPointType="SilverLightFSharp.MyApp" RuntimeVersion="2.0.31005.0">
<Deployment.Parts>
<AssemblyPart x:Name="SilverLightFSharp" Source="SilverLightFSharp.dll" />
<AssemblyPart x:Name="FSharp.Core" Source="FSharp.Core.dll" />
<AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
</Deployment.Parts>
</Deployment>

I'll also need a test html page to host my silverlight application. I created a TestPage.html to host my Silverlight application. Please note that for the Silverlight control host has the source referencing the file simplebutton.xap. Not to worry, simplebutton.xap is merely a zip file that contains the following files:

  • AppManifest.xaml
  • FSharp.Core.dll
  • System.Windows.Control.dll
  • SilverlightFsharp.dll

Here's the TestPage.html code:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<!-- saved from url=(0014)about:internet -->
<head>
<title>SilverlightFSharp</title>

<style type="text/css">
html, body {
height: 100%;
overflow: auto;
}
body {
padding: 0;
margin: 0;
}
#silverlightControlHost {
height: 100%;
}
</style>

<script type="text/javascript">
function onSilverlightError(sender, args) {

var appSource = "";
if (sender != null && sender != 0) {
appSource = sender.getHost().Source;
}
var errorType = args.ErrorType;
var iErrorCode = args.ErrorCode;

var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n" ;

errMsg += "Code: "+ iErrorCode + " \n";
errMsg += "Category: " + errorType + " \n";
errMsg += "Message: " + args.ErrorMessage + " \n";

if (errorType == "ParserError")
{
errMsg += "File: " + args.xamlFile + " \n";
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
else if (errorType == "RuntimeError")
{
if (args.lineNumber != 0)
{
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
errMsg += "MethodName: " + args.methodName + " \n";
}

throw new Error(errMsg);
}
</script>
</head>

<body>
<!-- Runtime errors from Silverlight will be displayed here.
This will contain debugging information and should be removed or hidden when debugging is completed -->
<div id='errorLocation' style="font-size: small;color: Gray;"></div>

<div id="silverlightControlHost">
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="simplebutton.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
</a>
</object>
<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
</div>
</body>
</html>

After I copy simplebutton.xap and TestPage.html to my IIS webserver, I am rewarded with the following results: