3 people like it.
Like the snippet!
Map for ObservableCollection
The snippet implements 'map' and 'init' functions for the 'ObservableCollection' type. These are similar to well-known functions for sequences, but 'map' works in an incremental fashion. When the source collection changes, the resulting collection is updated.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
|
open System.Collections.Specialized
open System.Collections.ObjectModel
module ObservableCollection =
/// Initialize observable collection
let init n f = ObservableCollection<_>(List.init n f)
/// Incremental map for observable collections
let map f (oc:ObservableCollection<'T>) =
// Create a resulting collection based on current elements
let res = ObservableCollection<_>(Seq.map f oc)
// Watch for changes in the source collection
oc.CollectionChanged.Add(fun change ->
printfn "%A" change.Action
match change.Action with
| NotifyCollectionChangedAction.Add ->
// Apply 'f' to all new elements and add them to the result
change.NewItems |> Seq.cast<'T> |> Seq.iteri (fun index item ->
res.Insert(change.NewStartingIndex + index, f item))
| NotifyCollectionChangedAction.Move ->
// Move element in the resulting collection
res.Move(change.OldStartingIndex, change.NewStartingIndex)
| NotifyCollectionChangedAction.Remove ->
// Remove element in the result
res.RemoveAt(change.OldStartingIndex)
| NotifyCollectionChangedAction.Replace ->
// Replace element with a new one (processed using 'f')
change.NewItems |> Seq.cast<'T> |> Seq.iteri (fun index item ->
res.[change.NewStartingIndex + index] <- f item)
| NotifyCollectionChangedAction.Reset ->
// Clear everything
res.Clear()
| _ -> failwith "Unexpected action!" )
res
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
|
// Create source collection and result using 'map'
let src = ObservableCollection.init 5 (fun n -> n)
let res = ObservableCollection.map (fun x ->
printfn "processing %d" x; x * 10) src
// Manipulate elements in the source
src.Move(0, 1)
src.Remove(0)
src.Clear()
src.Add(5)
src.Insert(0, 3)
src.[0] <- 1
// Compare the original and the result
printfn "%A" (Seq.zip src res |> List.ofSeq)
|
namespace System
namespace System.Collections
namespace System.Collections.Specialized
namespace System.Collections.ObjectModel
Multiple items
type ObservableCollection<'T> =
inherit Collection<'T>
new : unit -> ObservableCollection<'T> + 2 overloads
member Move : oldIndex:int * newIndex:int -> unit
event CollectionChanged : NotifyCollectionChangedEventHandler
Full name: System.Collections.ObjectModel.ObservableCollection<_>
--------------------
ObservableCollection() : unit
ObservableCollection(list: System.Collections.Generic.List<'T>) : unit
ObservableCollection(collection: System.Collections.Generic.IEnumerable<'T>) : unit
val init : n:int -> f:(int -> 'a) -> ObservableCollection<'a>
Full name: Script.ObservableCollection.init
Initialize observable collection
val n : int
val f : (int -> 'a)
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val init : length:int -> initializer:(int -> 'T) -> 'T list
Full name: Microsoft.FSharp.Collections.List.init
val map : f:('T -> 'a) -> oc:ObservableCollection<'T> -> ObservableCollection<'a>
Full name: Script.ObservableCollection.map
Incremental map for observable collections
val f : ('T -> 'a)
val oc : ObservableCollection<'T>
val res : ObservableCollection<'a>
module Seq
from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
event ObservableCollection.CollectionChanged: IEvent<NotifyCollectionChangedEventHandler,NotifyCollectionChangedEventArgs>
member System.IObservable.Add : callback:('T -> unit) -> unit
val change : NotifyCollectionChangedEventArgs
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
property NotifyCollectionChangedEventArgs.Action: NotifyCollectionChangedAction
type NotifyCollectionChangedAction =
| Add = 0
| Remove = 1
| Replace = 2
| Move = 3
| Reset = 4
Full name: System.Collections.Specialized.NotifyCollectionChangedAction
field NotifyCollectionChangedAction.Add = 0
property NotifyCollectionChangedEventArgs.NewItems: System.Collections.IList
val cast : source:System.Collections.IEnumerable -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.cast
val iteri : action:(int -> 'T -> unit) -> source:seq<'T> -> unit
Full name: Microsoft.FSharp.Collections.Seq.iteri
val index : int
val item : 'T
Collection.Insert(index: int, item: 'a) : unit
property NotifyCollectionChangedEventArgs.NewStartingIndex: int
field NotifyCollectionChangedAction.Move = 3
ObservableCollection.Move(oldIndex: int, newIndex: int) : unit
property NotifyCollectionChangedEventArgs.OldStartingIndex: int
field NotifyCollectionChangedAction.Remove = 1
Collection.RemoveAt(index: int) : unit
field NotifyCollectionChangedAction.Replace = 2
field NotifyCollectionChangedAction.Reset = 4
Collection.Clear() : unit
val failwith : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.failwith
val src : ObservableCollection<int>
Full name: Script.src
val res : ObservableCollection<int>
Full name: Script.res
val x : int
Collection.Remove(item: int) : bool
Collection.Add(item: int) : unit
Collection.Insert(index: int, item: int) : unit
val zip : source1:seq<'T1> -> source2:seq<'T2> -> seq<'T1 * 'T2>
Full name: Microsoft.FSharp.Collections.Seq.zip
val ofSeq : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.List.ofSeq
More information