3 people like it.

Structural BeginUpdate / EndUpdate with Lambda

Several WinForms controls, like TreeView and ListView, implement methods BeginUpdate and EndUpdate, which suspend repainting of the control while items are being individually added to a control, preventing flicker caused by rapid repainting. But using BeginUpdate and EndUpdate is very imperative, and opens up the possibility for bugs, such as neglecting to call the matching EndUpdate. An obvious improvement would be to create an extension method on types implementing this pattern which takes a unit -> unit lambda which is executed between update pairs. But the pattern is only conventional, rather than through a common base class or interface. Hence this presents a reasonable opportunity to use F#'s statically resolved structural type system to implement a function which only works on Control types with the correct structural signature.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
module Control =
    let inline update< ^a when ^a :(member BeginUpdate: unit -> unit) 
                       and ^a : (member EndUpdate: unit -> unit)> (this: ^a) f =
        (^a : (member BeginUpdate: unit -> unit) (this))
        f()
        (^a : (member EndUpdate: unit -> unit) (this))

module Example =
    open System.Windows.Forms
    let tv = new TreeView()
    Control.update tv <| fun () ->
            for i in 1..20 do
                tv.Nodes.Add(new TreeNode(i |> string)) |> ignore
namespace Microsoft.FSharp.Control
val update : this:'a -> f:(unit -> unit) -> unit (requires member BeginUpdate and member EndUpdate)

Full name: Script.Control.update
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val this : 'a (requires member BeginUpdate and member EndUpdate)
val f : (unit -> unit)
module Example

from Script
namespace System
namespace System.Windows
namespace System.Windows.Forms
val tv : TreeView

Full name: Script.Example.tv
Multiple items
type TreeView =
  inherit Control
  new : unit -> TreeView
  member BackColor : Color with get, set
  member BackgroundImage : Image with get, set
  member BackgroundImageLayout : ImageLayout with get, set
  member BeginUpdate : unit -> unit
  member BorderStyle : BorderStyle with get, set
  member CheckBoxes : bool with get, set
  member CollapseAll : unit -> unit
  member DrawMode : TreeViewDrawMode with get, set
  member EndUpdate : unit -> unit
  ...

Full name: System.Windows.Forms.TreeView

--------------------
TreeView() : unit
Multiple items
type Control =
  inherit Component
  new : unit -> Control + 4 overloads
  member AccessibilityObject : AccessibleObject
  member AccessibleDefaultActionDescription : string with get, set
  member AccessibleDescription : string with get, set
  member AccessibleName : string with get, set
  member AccessibleRole : AccessibleRole with get, set
  member AllowDrop : bool with get, set
  member Anchor : AnchorStyles with get, set
  member AutoScrollOffset : Point with get, set
  member AutoSize : bool with get, set
  ...
  nested type ControlAccessibleObject
  nested type ControlCollection

Full name: System.Windows.Forms.Control

--------------------
Control() : unit
Control(text: string) : unit
Control(parent: Control, text: string) : unit
Control(text: string, left: int, top: int, width: int, height: int) : unit
Control(parent: Control, text: string, left: int, top: int, width: int, height: int) : unit
val i : int32
property TreeView.Nodes: TreeNodeCollection
TreeNodeCollection.Add(node: TreeNode) : int
TreeNodeCollection.Add(text: string) : TreeNode
TreeNodeCollection.Add(key: string, text: string) : TreeNode
TreeNodeCollection.Add(key: string, text: string, imageKey: string) : TreeNode
TreeNodeCollection.Add(key: string, text: string, imageIndex: int) : TreeNode
TreeNodeCollection.Add(key: string, text: string, imageKey: string, selectedImageKey: string) : TreeNode
TreeNodeCollection.Add(key: string, text: string, imageIndex: int, selectedImageIndex: int) : TreeNode
Multiple items
type TreeNode =
  inherit MarshalByRefObject
  new : unit -> TreeNode + 4 overloads
  member BackColor : Color with get, set
  member BeginEdit : unit -> unit
  member Bounds : Rectangle
  member Checked : bool with get, set
  member Clone : unit -> obj
  member Collapse : unit -> unit + 1 overload
  member ContextMenu : ContextMenu with get, set
  member ContextMenuStrip : ContextMenuStrip with get, set
  member EndEdit : cancel:bool -> unit
  ...

Full name: System.Windows.Forms.TreeNode

--------------------
TreeNode() : unit
TreeNode(text: string) : unit
TreeNode(text: string, children: TreeNode []) : unit
TreeNode(text: string, imageIndex: int, selectedImageIndex: int) : unit
TreeNode(text: string, imageIndex: int, selectedImageIndex: int, children: TreeNode []) : unit
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore

More information

Link:http://fssnip.net/4Z
Posted:5 years ago
Author:Stephen Swensen
Tags: f# , winforms