Home > Uncategorized > Programming WPF user interfaces using F# workflows

Programming WPF user interfaces using F# workflows

References: Real world functional programming, First Class Events (Matthew Podwysocki), First Class Events (Don Syme), Cancellation (LukeH)

I rewrote the sample from real world functional programming using F# visual studio 2010 version and I replaced legacy windows forms with WPF. This was the result:

open System.Windows

open System.Windows.Controls

open System.Windows.Controls.Primitives

open System

open System.Windows.Shapes

open System.Drawing


let mutable globalGuiContext : System.Threading.SynchronizationContext = null


let drawLine(canvas : Canvas, (x1, y1), (x2, y2)) =

    let line = new Line()

    line.X1 <- float x1

    line.Y1 <- float y1

    line.X2 <- float x2

    line.Y2 <- float y2

    line.Stroke <- System.Windows.Media.Brushes.LightSteelBlue


    canvas.Children.Add(line) |> ignore


let rec drawingLoop(canvas : Canvas, from) = async {

    // Wait for the next mouse action

    let! move = Async.AwaitEvent(canvas.MouseMove)

    let pos = move.GetPosition(canvas)

    if move.LeftButton = Input.MouseButtonState.Pressed then

      // Refresh rectangle and continue in the ‘Drawing’ state     

      drawLine(canvas, from, (pos.X, pos.Y))

      return! drawingLoop(canvas, from)


      // Return end location to the ‘Waiting’ state

      return (pos.X, pos.Y) }


let waitingLoop(canvas : Canvas) = async {

    // Repeat the loop after drawing finishes

    while true do

      let! down = Async.AwaitEvent(canvas.MouseDown)     

      do! Async.SwitchToContext(globalGuiContext)

      let downPos = down.GetPosition(canvas)

      if down.LeftButton = Input.MouseButtonState.Pressed then

        // Transition to the ‘Drawing’ state

        let! upPos = drawingLoop(canvas, (downPos.X, downPos.Y))

        do printfn "Drawn line (%A, %A)" downPos upPos }


let doLayout() =

    let window = new Window()

    window.Title <- "Interaction test"

    window.Width <- 400.0

    window.Height <- 400.0

    window.Loaded.Add(fun _ -> globalGuiContext <- System.Threading.SynchronizationContext.Current)

    let canvas = new Canvas()

    canvas.Background <- System.Windows.Media.Brushes.Beige

    canvas.Opacity <- 1.0

    window.Content <- canvas

    (window, canvas)


let main() =

    let app = Application(ShutdownMode=ShutdownMode.OnMainWindowClose) in

    let (window,canvas) = doLayout()


    app.Run(window) |> ignore



do main()


Frankly, I think this approach to gui interaction code looks very promising and I hope to have time to play more with it.

Categories: Uncategorized
  1. February 18, 2015 at 6:33 am

    Hi Daniel. Thanks for this post.

    I’ve just been playing with Tomas Petrieck’s Chap 16 Version 3 code, and was wondering how to use WPF.

    Also tried Neil Danson recent Simplifying State with Async (with XNA/WPF examples)
    “… The addLine async workflow is where the magic happens …”
    He’s into XNA games.

    My art project Symmorphmetry(tm)

    using Refolding Planar Polygons RPP app is more like a drawing app.
    So the interest in Tomas’ code.
    Not sure if Neil’s gui loop would work for drawing, but will poke around some more there.

    Refolding Planar Polygons by Iben O’Brien and Demaine —
    Movies and everything.

    This paper describes an implementation of an algorithm for the refolding of multiple polygons with a guarantee of non-intersection.
    It has a gui I currently use as a guide.
    The report is available here and the project source code is available here.

    Finally, recently I saw this fun kaleidoscopes post
    Playing around with the kaleidoscope
    Posted on February 5, 2014

    Best regards,
    Art Scott

  2. February 18, 2015 at 6:34 am

    Reblogged this on Symmorphmetry.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: