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", &x) then...
- PropertyPath wouldn’t work with a string, it requires the actual property “PropertyPath(UIElement.OpacityProperty)” (from here)
Hey Matt glad to see that you’re still working hard. How’s life after the mothership?
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