Nov 092009

I encountered a ton of difficulties while porting code from C# to F#. Fortunately / unfortunately, so have many other people. Thankfully they took the time to write about these problems so my solutions were often only a quick search away. Here is a collection of some of the finds that were able to help me in my endeavors.

I have done my best to attribute sources, and as always feedback is very much appreciated. Also, I will be updating my code viewer as soon as possible to stop it from embedding html smiley faces.

1. Data Templates

Unfortunately the only way to build Data Templates in code is being deprecated, which means we have to resort to writing Data Templates in XAML as a string. This string is then loaded using XamlReader as per the following code.

let loadFromString xaml =
    use sr = new StringReader(xaml)
    use xr = XmlReader.Create(sr)
    XamlReader.Load xr

Steve Horsfeild has a good write up on this here

2. Attached Dependency Properties

For ages I tried to  figure out why my attached properties were not showing up in the XAML intellisense. It turns out that I was missing the Get and Set functions for the property, as per below;

    static let useHoverProperty =
                    DependencyProperty.RegisterAttached(
                     "UseHover", typeof<bool>, typeof<HoverInteractor>)

    static member public SetUseHover(d:DependencyObject, _use:bool) = d.SetValue(useHoverProperty, _use)
    static member public GetUseHover(d:DependencyObject) = d.GetValue(useHoverProperty) :?> bool

3. Using options instead of Null

I use this when a attribute is begin set at runtime and I know that no function will call the attribute until after it has been set. (from here)

“Nullable” member

    static let mutable draggedElt = None

    static member private DraggedElt
        with get() = match draggedElt with | Some(v) -> v | _ -> failwith "initialization fail"
        and set(x:UIElement) = draggedElt <- Some(x)

Check for “null”:

match scrollOwner with
| Some(v) -> v.InvalidateScrollInfo()
| None -> ()

From here

4. Removing event handlers

let rec eventHandler = EventHandler(fun o e ->

    // Hide the Viewport
    this.viewport.Visibility <- Visibility.Hidden
    Panel.SetZIndex(this.backChildContainer, 0)

    // Show the FrontChild
    this.frontChildContainer.Visibility <- Visibility.Visible
    dockAnim.Completed.RemoveHandler(eventHandler)
    )

However, sometimes you can’t keep a reference to the delegate instance. Fortunately you don’t have to. The following code works as the object passed into Remove() must match the associated signature, but not necessarily the actual delegate instance you wish to remove. (Apress: Pro C# 2008 and the .Net 3.5 Platform)

    override this.StartListening(source:obj) =
        let evtSource = source :?> DataSource
        evtSource.DataChanged.AddHandler(Handler<EventArgs>(this.PrivateOnDataChanged))

    override this.StopListening(source:obj) =
        let evtSource = source :?> DataSource
        evtSource.DataChanged.RemoveHandler(Handler<EventArgs>(this.PrivateOnDataChanged))

4. Property changed events

This is pretty straight forward (from here)

let propertyChanged = Event<_,_>()
let notify obj s = propertyChanged.Trigger(obj, PropertyChangedEventArgs(s))

interface INotifyPropertyChanged with
    [<CLIEvent>]
    member this.PropertyChanged = propertyChanged.Publish

6. Runtime casting:

The following is the equivilent for using as (C# keyword), and then checking for Null. (from here)

   match b1 with
   | :? Derived1 as derived1 -> derived1.F()
   | _ -> ()

Other bits and pieces;

  • Accessing members in interfaces. It is a little odd but you have to cast the object to the interface type before you can call on the interface member: “(mark :> CouchDBDocument).DocType” (from here)
  • Pass ‘by ref’ into a function can be done by using the prefix ‘&” operator on a mutable (from here)
let mutable x = 1
if d.TryGetValue("foo", &amp;x) then...
 
  • PropertyPath wouldn’t work with a string, it requires the actual property “PropertyPath(UIElement.OpacityProperty)”  (from here)
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • RSS
  • StumbleUpon
  • Twitter
Posted by Matt Tagged with: , ,

2 Comments to “Lessons learned in porting C# to F# (WPF)”

  1. Isaac says:

    Hey Matt glad to see that you’re still working hard. How’s life after the mothership?

  2. Matt says:

    Hey Isaac, I do miss all the great ppl at MS but things are going great :) I’m doing what I love! I’ll send you an email.
    Matt

Leave a Reply

(required)

(required)