open System open System.Collections.Generic open System.ComponentModel // SortableBindingList in F# adapted from msmolcic on Stack Overflow // https://stackoverflow.com/questions/23661195/datagridview-using-sortablebindinglist type SortableBindingList<'T>(list:IEnumerable<'T>) = inherit BindingList<'T>(List(list)) let mutable isSorted = false let mutable sortDirection = ListSortDirection.Ascending let mutable sortProperty : PropertyDescriptor option = None new () = SortableBindingList(Seq.empty<'T>) override l.ApplySortCore(prop, direction) = let raiseEx () = new NotSupportedException("Cannot sort by " + prop.Name + ". This" + prop.PropertyType.ToString() + " does not implement IComparable") |> raise match prop.PropertyType.GetInterface("IComparable") with | null -> if prop.PropertyType.IsValueType then match Nullable.GetUnderlyingType(prop.PropertyType) with | null -> raiseEx() | t -> match t.GetInterface("IComparable") with | null -> raiseEx() | _ -> () // Just fall through the match case and apply the sort | _ -> () // Just fall through the match case and apply the sort // IComparable interface is supported, so apply the sort let query = base.Items :> IEnumerable<'T> sortProperty <- Some prop sortDirection <- direction let sorted = match direction with | ListSortDirection.Ascending -> query |> Seq.sortBy (fun i -> prop.GetValue(i) :?> IComparable) | _ -> query |> Seq.sortByDescending (fun i -> prop.GetValue(i) :?> IComparable) |> Array.ofSeq // Can't access protected "Items" within lambda, so use this for loop construct for i in [0 .. Array.length sorted - 1] do l.Items.[i] <- sorted.[i] isSorted <- true l.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)) override __.SortPropertyCore = match sortProperty with | Some sp -> sp | _ -> new System.NullReferenceException("Sortable property was null.") |> raise override __.SortDirectionCore = sortDirection override __.SupportsSortingCore = true override __.IsSortedCore = isSorted