F# - Interacting With WPF Dispatcher Via F# Interactive Window

by Dean 8. October 2010 08:44

Heres an interesting scenario that was discussed with me by one of the quants in the front-office team yesterday.

"Can I invoke a WPF Window/Control to popup from the FSI window in Visual Studio ?" - "Yes, thats easy I said"....

"and then interact with it ASYNCHRONOUSLY via F# commands in the FSI window ?" - "hmmmm, I said"

So the first bit is easy and has been done many times before with WPF and Winforms, and that is mainly to instantiate UI controls and popups from within Fsharp Interactive, and update these controls when running F# commands..... but....... you're doing your updates synchronously on the main UI thread !

What if the update your running is a long-running task, that WPF popup is going to freeze on you, and to solve it you are facing the classic issue of STA thread affinity with either WPF or Winforms.

The common solution in standard WPF/Winforms apps is to marshall messages to the UI pump via delegates, but how would that work in F# interactive ?

After a little head-scratching, I figured it out, and here is a sample of how its done below:

 

#light

#r "WindowsBase"
#r "PresentationCore"
#r "PresentationFramework"

open System
open System.Windows
open System.Windows.Controls
open System.Threading
open System.Windows.Threading

// create a reference to a WPF control in interactive window
let mutable (wp : TextBlock) = null

// create a new WPF gui thread with a running dispatcher and message pump
let thread = new System.Threading.Thread(fun() ->
    let window = new System.Windows.Window(Name="Test",Width=500.0,Height=500.0)
    wp <- new TextBlock()
    wp.Text <- "test1"
    window.Content <- wp
    window.Visibility <- Visibility.Visible
    window.Show()
    window.Closed.Add(fun e ->
        Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background)
        Thread.CurrentThread.Abort())
    Dispatcher.Run()
    )
thread.SetApartmentState(ApartmentState.STA)
thread.IsBackground <- true

// start the thread, which will invoke the popup ui
thread.Start()

// once WPF window is up, you can marshall updates via its running dispatcher
wp.Dispatcher.BeginInvoke(Action(fun _ -> wp.Text <- "test2")) |> ignore

To test this, run all but the last line in the interactive window, and you should see a popup like this:

 

 

Then run the final line, which marshalls the update onto the new gui thread, and you get this

 

Proving the solution:

So what this means now is that we can create sophosticated WPF controls, invoke them in the FSI window, and then apply long-running upddates via FSI without the WPF window freezing on us.

That should keep the trading desk guys happy :)

Dean

Tags: , , ,

F# | Threading | WPF

Lightweight ‘O/R Mapping’ in F# Interactive

by Dean 26. April 2010 21:15

I’ve been playing a lot with F# lately, particularly in the area of financial option modelling, which requires quite a lot of number crunching – a perfect scenario for tinkering around in F# interactive.

However, I need to get data out of my data store, and use it to create collections of records, that represent the data that I need.

This was becoming a little cumbersome, so I thought I’d create a little ORM function to do the trick

open System.Data.SqlClient
open Microsoft.FSharp.Reflection
 
let BuildData<'T> (connection:string, command:string) = 
    let conn = new SqlConnection(connection)
    let comm = new SqlCommand(command,conn)
    let recordType = typeof<'T>
    let fieldCount = FSharpType.GetRecordFields(recordType).Length
    conn.Open()
    let db = comm.ExecuteReader()
    let rec populate (reader:SqlDataReader) (l:'T list) = 
        match reader.Read() with
        | false -> l
        | _ -> 
            let vals = Array.create<obj> fieldCount null
            ignore(reader.GetValues(vals))
            let dataObj = FSharpValue.MakeRecord(recordType,vals) :?> 'T 
            let x = dataObj::l
            populate reader x
    let  data = populate db []
    conn.Close()
    data

run the above in interactive, and you’ll get

val BuildData : string * string -> 'T list

now lets give it a spin

 

type pricedata = { Price : Decimal; Symbol : String; PriceDate : DateTime }
let conn = "Data Source=DEAN-PC\SQLEXPRESS;Initial Catalog=StockData;Integrated Security=SSPI"
let comm = "select price, symbol, pricedate from symboldata where symbol = 'AA'"
let data = BuildData<pricedata>(conn,comm)

so we now have a strongly-typed collection, ready for pumping into our financial modelling functions

or alternatively, you could display the data in a grid :-

open System.Windows.Forms
 
let grid data =
    let form = new System.Windows.Forms.Form(Visible=true,TopMost=true)
    let g = new System.Windows.Forms.DataGrid(Dock = DockStyle.Fill, Visible=true)
    g.DataSource <- List.toArray data
    form.Controls.Add(g) 
 
grid data

and the result is like this

stockdata

Tags: , , ,

F# | DataBinding

F# And MVVM – A Simple ViewModel

by Dean 12. April 2010 20:51

For many years, OOP abstractions and design patterns have been the cornerstones of my development methodology as a senior C# developer in investment banking.

However, over the last year or so I have taken quite a shine to Microsoft’s new FP language (F#), not just because purely functional program code is concise powerful and elegant, but because the eclectic mix of functional and OOP paradigms in F# enable me to develop better, faster, stronger and more maintainable applications.

In investment banking, the business has been changing fast, and being able to get production quality WPF apps onto the trader desks has been a big priority, and with F# I find myself more able to meet that challenge.

The WPF design pattern ‘du jour’ is MVVM. Anyone who’s serious about enterprise-strength development in WPF would have come across this pattern and probably have used it at some point in the recent past.

Detailed below is a very basic implementation where :-

  1. There is a WPF project that contains only Views
  2. There is a C# ‘model’ project that contains only the generated classes from SqlMetal (for Linq to SQL)
  3. The is an F# code library project that contains my ViewModel

The F# ViewModel is a very simple one, but it covers all the main bases:-

  1. It has a generic ICommand implementation for command binding
  2. It implements INotifyPropertyChanged for change notifications
  3. It has Data for binding

So here it is

#light
module FSharpMVVM
 
open System
open System.Windows.Input
open System.Data.SqlClient
open System.ComponentModel
open FsMVVM.DAL
 
// below is our Linq-SQL data context, created via SqlMetal and in a separate
// C# project - as SqlMetal doesnt generate F# yet *)
 
let ctx = new DataClassesDataContext()
 
// an implemnentation of a generic ICommand, that takes two functions
// one to see if the command can be executed, and one to execute the command 
 
type FuncCommand (canExec:(obj -> bool),doExec:(obj -> unit)) =
    let cecEvent = new DelegateEvent<EventHandler>()
    interface ICommand with
        [<CLIEvent>]
        member x.CanExecuteChanged = cecEvent.Publish
        member x.CanExecute arg = canExec(arg)
        member x.Execute arg = doExec(arg)
 
// Our ViewModel is below
 
type MainViewModel() =  
    let mutable prods = Seq.toList ctx.Products 
    let a =  new PropertyChangedEventArgs("ProductData")
    let propChangedEvent = new DelegateEvent<PropertyChangedEventHandler>()
    interface INotifyPropertyChanged with 
        [<CLIEvent>]
        member x.PropertyChanged = propChangedEvent.Publish
    member x.ProductData with get() = prods
    member x.FilterCommand = 
        new FuncCommand(
            (fun d -> not(Seq.isEmpty ctx.Products)),
            (fun e -> prods <- Seq.toList ctx.Products 
                    |> List.filter (
                        fun p -> p.ProductName.Contains(e.ToString()));
                        propChangedEvent.Trigger([| box x; box a|])))

 

and below is the simple View (XAML)

 

<Window x:Class="FsMVVM.WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Margin="5">
            <TextBox Name="searchText" MinWidth="100" />
            <Button Content="Search" Command="{Binding FilterCommand}" 
                    CommandParameter="{Binding ElementName=searchText, Path=Text}" />
        </StackPanel>
        <ListView ItemsSource="{Binding ProductData}" Grid.Row="1">
            <ListView.View>
                <GridView>
                    <GridView.Columns>
                        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding ProductName}" />
                    </GridView.Columns>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

 

and finally, its wired up in the code-behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new FSharpMVVM.MainViewModel();
    }
}

and that's all it takes

Now, I know that there isnt a great deal of functional programming in this example, but now I have the building blocks for a more complex ViewModel, that will no doubt include a great deal more FP before it is finished

 

Dean

Tags: ,

DataBinding | F# | MVVM

RecentComments

Comment RSS
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012 Dean Chalk's Blog