Drag and Drop in Silverlight with F# and Asynchronous Workflows

Posted by knotig on Stack Overflow See other posts from Stack Overflow or by knotig
Published on 2010-06-06T20:26:13Z Indexed on 2010/06/06 20:32 UTC
Read the original article Hit count: 268

Filed under:
|
|
|

Hello everyone!

I'm trying to implement drag and drop in Silverlight using F# and asynchronous workflows.

I'm simply trying to drag around a rectangle on the canvas, using two loops for the the two states (waiting and dragging), an idea I got from Tomas Petricek's book "Real-world Functional Programming", but I ran into a problem:

Unlike WPF or WinForms, Silverlight's MouseEventArgs do not carry information about the button state, so I can't return from the drag-loop by checking if the left mouse button is no longer pressed. I only managed to solve this by introducing a mutable flag.

Would anyone have a solution for this, that does not involve mutable state?

Here's the relevant code part (please excuse the sloppy dragging code, which snaps the rectangle to the mouse pointer):

type MainPage() as this =
    inherit UserControl()
    do
        Application.LoadComponent(this, new System.Uri("/SilverlightApplication1;component/Page.xaml", System.UriKind.Relative))
    let layoutRoot : Canvas = downcast this.FindName("LayoutRoot")
    let rectangle1 : Rectangle = downcast this.FindName("Rectangle1")

    let mutable isDragged = false

    do
        rectangle1.MouseLeftButtonUp.Add(fun _ -> isDragged <- false)

        let rec drag() = async {
            let! args = layoutRoot.MouseMove |> Async.AwaitEvent
            if (isDragged) then
                Canvas.SetLeft(rectangle1, args.GetPosition(layoutRoot).X)
                Canvas.SetTop(rectangle1, args.GetPosition(layoutRoot).Y)
                return! drag()
            else
                return()
            } 
        let wait() = async {
            while true do
                let! args = Async.AwaitEvent rectangle1.MouseLeftButtonDown
                isDragged <- true
                do! drag()
            }

        Async.StartImmediate(wait())
        ()

Thank you very much for your time!

© Stack Overflow or respective owner

Related posts about Silverlight

Related posts about F#