by February 4, 2012on
Lately I wanted to use a WPF ListBox with selectable items (with a DataTemplate and a simple CheckBox attached). In order to properly use such a thing you should implement the
INotifyPropertyChanged interface 1. I hadn’t used events in F# before so had to experiment a few things to get it right.
The solution was to implement a CheckItem class that wraps the selection functionality and the implementation of the
INotifyPropertyChanged interface. This is what it looks like:
open System.ComponentModel open Microsoft.FSharp.Quotations.Patterns /// Observable object class implementing the INotifyPropertyChanged /// interface type ObservableItem() = let propertyChanged = Event<_,_>() let getPropertyName = function | PropertyGet(_, p, _) -> p.Name | _ -> invalidOp "Invalid expression argument: expecting property getter" interface INotifyPropertyChanged with [<CLIEvent>] member this.PropertyChanged = propertyChanged.Publish member this.NotifyPropertyChanged name = propertyChanged.Trigger(this, PropertyChangedEventArgs(name)) member this.NotifyPropertyChanged expr = expr |> getPropertyName |> this.NotifyPropertyChanged /// Simple wrapper class for a selectable item type CheckItem<'a>(item : 'a) = inherit ObservableItem() let mutable _isSelected = true let _item = item member this.Item with get () = _item member this.IsSelected with get () = _isSelected and set value = _isSelected <- value this.NotifyPropertyChanged <@ this.IsSelected @>
There are a few things worth noting here: The first interesting thing is the attribute CLIEventAttribute 2 that allows us the use a more consise way of implementing events. Basically it adds the necessary CLI metadata to the event and implements the add_EventName and remove_EventName methods.
The second interesting fact is the usage of F# quotations to attach the right property name to the
PropertyChangedEventArgs structure. Instead of specifying a string constant it is possible to use a property expression.