Sunday, March 08, 2009

F# Silverlight, XAML and opening local files

I’m working through more examples in the book Silverlight 2 Recipes.  While it has been an interesting exercise to manually convert the XAML examples into F# code, it detracted me from learning about other aspects of Silverlight technology.  In this particular sample code, I decided to take the XAML output and dynamically load it as per the example from recipe 2-5.  Of course, once you load the UI controls via XAML, you’ll need to find those controls as per example from recipe 2-3 from the book.  Finally, the recipe I really wanted to develop is recipe 2-7 where the Silverlight app loads local files.  Below is the sample code:


#light
namespace SilverLightFSharp

open System
open System.IO
open System.IO.IsolatedStorage
open System.Windows
open System.Windows.Controls
open System.Windows.Media
open System.ServiceModel
open System.Windows.Markup
open System.Windows.Browser
open List

// Combining recipes 2-3,2-5 and 2-7 from Silverlight 2 Recipes book
// Dynamically loading XAML from managed code
// Find an element in XAML
// Opening local files
type MyPage() = class
inherit UserControl()

do
let xaml =
"<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:d='http://schemas.microsoft.com/expression/blend/2008'
xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'
mc:Ignorable='d'>
<Grid.Background>
<LinearGradientBrush EndPoint='0.5,1' StartPoint='0.5,0'>
<GradientStop Color='#FF000000'/>
<GradientStop Color='#FFFFFFFF' Offset='1'/>
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height='0.117*'/>
<RowDefinition Height='0.79*'/>
<RowDefinition Height='0.093*'/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='0.058*'/>
<ColumnDefinition Width='0.252*'/>
<ColumnDefinition Width='0.64*'/>
<ColumnDefinition Width='0.05*'/>
</Grid.ColumnDefinitions>
<Button Height='28.9' HorizontalAlignment='Stretch' Margin='8,8,11,0'
VerticalAlignment='Top' Width='81.8' Grid.Column='1' Grid.Row='1'
Content='Select Files' d:LayoutOverrides='Height' x:Name='ButtonSelectFiles'/>
<TextBlock Margin='4,2,2,2' Grid.Column='1' Grid.Row='2' Text='Status'
TextWrapping='Wrap' Grid.ColumnSpan='2' x:Name='StatusLabel'/>
<Border Grid.Column='2' Grid.Row='1' Margin='0,0,0,0' CornerRadius='12'>
<Border.Background>
<LinearGradientBrush EndPoint='0.916999995708466,0.0890000015497208'
StartPoint='-0.0489999987185001,2.12400007247925'>
<GradientStop Color='#FF1D351E'/>
<GradientStop Color='#FF1D351E' Offset='1'/>
<GradientStop Color='#FFB7D8BA' Offset='0.50900000333786011'/>
</LinearGradientBrush>
</Border.Background>
<ListBox x:Name='FileList' Foreground='#FF000000' Height='217'
Width='236' Opacity='1'/>
</Border>
</Grid>"

// Load xaml dynamically
let grid = XamlReader.Load(xaml) :?> Grid

// Find the controls...
let status = grid.FindName("StatusLabel") :?> TextBlock
let btnSelect = grid.FindName("ButtonSelectFiles") :?> Button
let fileslist = grid.FindName("FileList") :?> ListBox

// open local files
btnSelect.Click.Add(fun e ->
let fileDlg = new OpenFileDialog(Filter="Image Files (*.jpg)|*.jpg|All Files (*.*)|*.*",
Multiselect=true,
FilterIndex=1)

let (=?!) (x: Nullable<'a>) (y:'a) = x.HasValue && x.Value = y

if (fileDlg.ShowDialog() =?! true )
then let files = fileDlg.Files
status.Text <- (files |> Seq.length |> sprintf "%i file(s) selected")
files |> Seq.iter (fileslist.Items.Add)
)

base.Width <- 400.0
base.Height <- 300.0
base.Content <- grid


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

No comments: