diff --git a/src/Elmish.WPF/Binding.fs b/src/Elmish.WPF/Binding.fs
index c95c56d9..87727208 100644
--- a/src/Elmish.WPF/Binding.fs
+++ b/src/Elmish.WPF/Binding.fs
@@ -8,2951 +8,765 @@ open System.Collections.ObjectModel
module Binding =
- open BindingData
-
- let internal mapData f binding =
- { Name = binding.Name
- Data = binding.Data |> f }
-
- /// Boxes the output parameter.
- /// Allows using a strongly-typed submodel binding (from a module ending in "T")
- /// in a binding list (rather than in a view model class member as normal).
- let boxT (binding: Binding<'b, 'msg, 't>) = BindingData.boxT |> mapData <| binding
-
- /// Unboxes the output parameter
- let unboxT (binding: Binding<'b, 'msg>): Binding<'b, 'msg, 't> = BindingData.unboxT |> mapData <| binding
-
- /// Maps the model of a binding via a contravariant mapping.
- let mapModel (f: 'a -> 'b) (binding: Binding<'b, 'msg, 't>) = f |> mapModel |> mapData <| binding
-
- /// Maps the message of a binding with access to the model via a covariant mapping.
- let mapMsgWithModel (f: 'a -> 'model -> 'b) (binding: Binding<'model, 'a, 't>) = f |> mapMsgWithModel |> mapData <| binding
-
- /// Maps the message of a binding via a covariant mapping.
- let mapMsg (f: 'a -> 'b) (binding: Binding<'model, 'a, 't>) = f |> mapMsg |> mapData <| binding
-
- /// Sets the message of a binding with access to the model.
- let setMsgWithModel (f: 'model -> 'b) (binding: Binding<'model, 'a, 't>) = f |> setMsgWithModel |> mapData <| binding
-
- /// Sets the message of a binding.
- let setMsg (msg: 'b) (binding: Binding<'model, 'a, 't>) = msg |> setMsg |> mapData <| binding
-
-
- /// Restricts the binding to models that satisfy the predicate after some model satisfies the predicate.
- let addSticky (predicate: 'model -> bool) (binding: Binding<'model, 'msg, 't>) = predicate |> addSticky |> mapData <| binding
-
- ///
- /// Adds caching to the given binding. The cache holds a single value and
- /// is invalidated after the given binding raises the
- /// PropertyChanged event.
- ///
- /// The binding to which caching is added.
- let addCaching (binding: Binding<'model, 'msg, 't>) : Binding<'model, 'msg, 't> =
- binding
- |> mapData addCaching
-
- ///
- /// Adds validation to the given binding using INotifyDataErrorInfo.
- ///
- /// Returns the errors associated with the given model.
- /// The binding to which validation is added.
- let addValidation (validate: 'model -> string list) (binding: Binding<'model, 'msg, 't>) : Binding<'model, 'msg, 't> =
- binding
- |> mapData (addValidation validate)
-
- ///
- /// Adds laziness to the updating of the given binding. If the models are considered equal,
- /// then updating of the given binding is skipped.
- ///
- /// Updating skipped when this function returns true.
- /// The binding to which the laziness is added.
- let addLazy (equals: 'model -> 'model -> bool) (binding: Binding<'model, 'msg, 't>) : Binding<'model, 'msg, 't> =
- binding
- |> mapData (addLazy equals)
-
- ///
- /// Alters the message stream via the given function.
- /// Ideally suited for use with Reactive Extensions.
- ///
- /// open FSharp.Control.Reactive
- /// let delay dispatch =
- /// let subject = Subject.broadcast
- /// let observable = subject :> System.IObservable<_>
- /// observable
- /// |> Observable.delay (System.TimeSpan.FromSeconds 1.0)
- /// |> Observable.subscribe dispatch
- /// |> ignore
- /// subject.OnNext
- ///
- /// // ...
- ///
- /// binding |> Binding.alterMsgStream delay
- ///
- ///
- /// The function that can alter the message stream.
- /// The binding of the altered message stream.
- let alterMsgStream (alteration: ('b -> unit) -> 'a -> unit) (binding: Binding<'model, 'a, 't>) : Binding<'model, 'b, 't> =
- binding
- |> mapData (alterMsgStream alteration)
-
-
- ///
- /// Strongly-typed bindings that update the view from the model.
- ///
- module OneWayT =
-
- /// Elemental instance of a one-way binding.
- let id<'a, 'msg> : string -> Binding<'a, 'msg, 'a> =
- OneWay.id
- |> createBindingT
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt x : Binding<'a option, 'msg, System.Nullable<'a>> =
- x
- |> id
- |> mapModel Option.toNullable
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt x : Binding<'a voption, 'msg, System.Nullable<'a>> =
- x
- |> id
- |> mapModel ValueOption.toNullable
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let optobj<'a, 'msg when 'a : null> : string -> Binding<'a option, 'msg, 'a> =
- id<'a, 'msg>
- >> mapModel Option.toObj
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let voptobj<'a, 'msg when 'a : null> : string -> Binding<'a voption, 'msg, 'a> =
- id<'a, 'msg>
- >> mapModel ValueOption.toObj
-
- ///
- /// Strongly-typed bindings that update the model from the view.
- ///
- module OneWayToSourceT =
-
- /// Elemental instance of a one-way-to-source binding.
- let id<'model, 'a> : string -> Binding<'model, 'a, 'a> =
- OneWayToSource.id
- |> createBindingT
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let optobj<'a, 'model when 'a : null> : string -> Binding<'model, 'a option, 'a> =
- id<'model, 'a>
- >> mapMsg Option.ofObj
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let voptobj<'a, 'model when 'a : null> : string -> Binding<'model, 'a voption, 'a> =
- id<'model, 'a>
- >> mapMsg ValueOption.ofObj
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt x : Binding<'model, 'a option, System.Nullable<'a>> =
- x
- |> id
- |> mapMsg Option.ofNullable
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt x : Binding<'model, 'a voption, System.Nullable<'a>> =
- x
- |> id
- |> mapMsg ValueOption.ofNullable
-
- ///
- /// Strongly-typed bindings that update both ways
- ///
- module TwoWayT =
-
- /// Elemental instance of a two-way binding.
- let id<'a> : string -> Binding<'a, 'a, 'a> =
- TwoWay.id
- |> createBindingT
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt x : Binding<'a option, 'a option, System.Nullable<'a>> =
- x
- |> id
- |> mapMsg Option.ofNullable
- |> mapModel Option.toNullable
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt x : Binding<'a voption, 'a voption, System.Nullable<'a>> =
- x
- |> id
- |> mapMsg ValueOption.ofNullable
- |> mapModel ValueOption.toNullable
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let optobj<'a when 'a : null> : string -> Binding<'a option, 'a option, 'a> =
- id<'a>
- >> mapModel Option.toObj
- >> mapMsg Option.ofObj
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let voptobj<'a when 'a : null> : string -> Binding<'a voption, 'a voption, 'a> =
- id<'a>
- >> mapMsg ValueOption.ofObj
- >> mapModel ValueOption.toObj
-
- ///
- /// The strongly-typed counterpart of Binding.oneWaySeq with parameter getId.
- /// Exposes an ObservableCollection of child items for binding.
- /// Allows a more efficient update than would be possible without using ids.
- ///
- module OneWaySeqT =
-
- ///
- /// Elemental instance of a OneWaySeqT binding
- ///
- /// Defines whether an item is "equal" and needs to be updated if the ids are the same
- /// Unique identifier for each item in the list (for efficient updates).
- let id itemEquals (getId: 'a -> 'id) : string -> Binding<_, 'msg, _> =
- OneWaySeq.create itemEquals getId
- |> createBindingT
-
- ///
- /// Strongly-typed bindings that dispatch messages from the view.
- ///
- module CmdT =
+ open BindingData
- ///
- /// Elemental instance of a Command binding.
- /// Creates a Command binding that only passes the CommandParameter)
- ///
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- /// Indicates whether the command can execute.
- let id<'model> uiBoundCmdParam canExec
- : string -> Binding<'model, obj, ICommand> =
- Cmd.createWithParam
- (fun p _ -> ValueSome p)
- canExec
- uiBoundCmdParam
- |> createBindingT
+ let internal mapData f binding =
+ { Name = binding.Name
+ Data = binding.Data |> f }
+
+ /// Boxes the output parameter.
+ /// Allows using a strongly-typed submodel binding (from a module ending in "T")
+ /// in a binding list (rather than in a view model class member as normal).
+ let boxT (binding: Binding<'b, 'msg, 't>) = BindingData.boxT |> mapData <| binding
+
+ /// Unboxes the output parameter
+ let unboxT (binding: Binding<'b, 'msg>) : Binding<'b, 'msg, 't> =
+ BindingData.unboxT |> mapData <| binding
+
+ /// Maps the model of a binding via a contravariant mapping.
+ let mapModel (f: 'a -> 'b) (binding: Binding<'b, 'msg, 't>) = f |> mapModel |> mapData <| binding
+
+ /// Maps the message of a binding with access to the model via a covariant mapping.
+ let mapMsgWithModel (f: 'a -> 'model -> 'b) (binding: Binding<'model, 'a, 't>) =
+ f |> mapMsgWithModel |> mapData <| binding
+
+ /// Maps the message of a binding via a covariant mapping.
+ let mapMsg (f: 'a -> 'b) (binding: Binding<'model, 'a, 't>) = f |> mapMsg |> mapData <| binding
+
+ /// Sets the message of a binding with access to the model.
+ let setMsgWithModel (f: 'model -> 'b) (binding: Binding<'model, 'a, 't>) =
+ f |> setMsgWithModel |> mapData <| binding
+
+ /// Sets the message of a binding.
+ let setMsg (msg: 'b) (binding: Binding<'model, 'a, 't>) = msg |> setMsg |> mapData <| binding
+
+
+ /// Restricts the binding to models that satisfy the predicate after some model satisfies the predicate.
+ let addSticky (predicate: 'model -> bool) (binding: Binding<'model, 'msg, 't>) =
+ predicate |> addSticky |> mapData <| binding
///
- /// Creates a Command binding that depends only on the model (not the
- /// CommandParameter).
+ /// Adds caching to the given binding. The cache holds a single value and
+ /// is invalidated after the given binding raises the
+ /// PropertyChanged event.
///
- /// Indicates whether the command can execute.
- /// Returns the message to dispatch.
- let model
- canExec
- (exec: 'model -> 'msg)
- : string -> Binding<'model, 'msg, ICommand> =
- id false (fun _ m -> m |> canExec)
- >> mapMsgWithModel (fun _ y -> y |> exec)
- >> addLazy (fun m1 m2 -> canExec m1 = canExec m2)
+ /// The binding to which caching is added.
+ let addCaching (binding: Binding<'model, 'msg, 't>) : Binding<'model, 'msg, 't> = binding |> mapData addCaching
///
- /// Creates a Command binding that dispatches the specified message.
+ /// Adds validation to the given binding using INotifyDataErrorInfo.
///
- /// Indicates whether the command can execute.
- /// The message to dispatch.
- let set
- canExec
- (msg: 'msg)
- : string -> Binding<'model, 'msg, ICommand> =
- id false (fun _ m -> m |> canExec)
- >> setMsg msg
+ /// Returns the errors associated with the given model.
+ /// The binding to which validation is added.
+ let addValidation
+ (validate: 'model -> string list)
+ (binding: Binding<'model, 'msg, 't>)
+ : Binding<'model, 'msg, 't> =
+ binding |> mapData (addValidation validate)
///
- /// Creates a Command binding that depends only on the model (not the
- /// CommandParameter) and always executes.
+ /// Adds laziness to the updating of the given binding. If the models are considered equal,
+ /// then updating of the given binding is skipped.
///
- /// Returns the message to dispatch.
- let modelAlways
- (exec: 'model -> 'msg)
- : string -> Binding<'model, 'msg, ICommand> =
- model (fun _ -> true) exec
+ /// Updating skipped when this function returns true.
+ /// The binding to which the laziness is added.
+ let addLazy (equals: 'model -> 'model -> bool) (binding: Binding<'model, 'msg, 't>) : Binding<'model, 'msg, 't> =
+ binding |> mapData (addLazy equals)
///
- /// Creates a Command binding that dispatches the specified message
- /// and always executes.
- ///
- /// The message to dispatch.
- let setAlways
- (msg: 'msg)
- : string -> Binding<'model, 'msg, ICommand> =
- set (fun _ -> true) msg
-
- module OneWay =
-
- /// Elemental instance of a one-way binding.
- let id<'a, 'msg> : string -> Binding<'a, 'msg> =
- OneWay.id
- |> createBinding
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt<'a, 'msg> : string -> Binding<'a option, 'msg> =
- id
- >> mapModel Option.box
-
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt<'a, 'msg> : string -> Binding<'a voption, 'msg> =
- id
- >> mapModel ValueOption.box
-
-
- module OneWayToSource =
-
- /// Elemental instance of a one-way-to-source binding.
- let id<'model, 'a> : string -> Binding<'model, 'a> =
- OneWayToSource.id
- |> createBinding
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt<'model, 'a> : string -> Binding<'model, 'a voption> =
- id<'model, obj>
- >> mapMsg ValueOption.unbox
-
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt<'model, 'a> : string -> Binding<'model, 'a option> =
- id<'model, obj>
- >> mapMsg Option.unbox
-
-
- module TwoWay =
-
- /// Elemental instance of a two-way binding.
- let id<'a> : string -> Binding<'a, 'a> =
- TwoWay.id
- |> createBinding
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let vopt<'a> : string -> Binding<'a voption, 'a voption> =
- id
- >> mapModel ValueOption.box
- >> mapMsg ValueOption.unbox
-
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- let opt<'a> : string -> Binding<'a option, 'a option> =
- id
- >> mapModel Option.box
- >> mapMsg Option.unbox
-
-
- module SubModelSelectedItem =
-
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
+ /// Alters the message stream via the given function.
+ /// Ideally suited for use with Reactive Extensions.
+ ///
+ /// open FSharp.Control.Reactive
+ /// let delay dispatch =
+ /// let subject = Subject.broadcast
+ /// let observable = subject :> System.IObservable<_>
+ /// observable
+ /// |> Observable.delay (System.TimeSpan.FromSeconds 1.0)
+ /// |> Observable.subscribe dispatch
+ /// |> ignore
+ /// subject.OnNext
///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- let vopt subModelSeqBindingName : string -> Binding<'id voption, 'id voption> =
- SubModelSelectedItem.create subModelSeqBindingName
- |> createBinding
- >> mapModel (ValueOption.map box)
- >> mapMsg (ValueOption.map unbox)
-
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
+ /// // ...
///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- let opt subModelSeqBindingName : string -> Binding<'id option, 'id option> =
- vopt subModelSeqBindingName
- >> mapModel ValueOption.ofOption
- >> mapMsg ValueOption.toOption
-
-
- module Cmd =
-
- let internal createWithParam exec canExec autoRequery =
- Cmd.createWithParam exec canExec autoRequery
- |> createBinding
-
- let internal create exec canExec =
- createWithParam
- (fun _ -> exec)
- (fun _ -> canExec)
- false
- >> addLazy (fun m1 m2 -> canExec m1 = canExec m2)
-
-
- module OneWaySeq =
+ /// binding |> Binding.alterMsgStream delay
+ ///
+ ///
+ /// The function that can alter the message stream.
+ /// The binding of the altered message stream.
+ let alterMsgStream
+ (alteration: ('b -> unit) -> 'a -> unit)
+ (binding: Binding<'model, 'a, 't>)
+ : Binding<'model, 'b, 't> =
+ binding |> mapData (alterMsgStream alteration)
- let internal create get itemEquals getId =
- OneWaySeq.create itemEquals getId
- |> BindingData.mapModel get
- |> createBinding
+ ///
+ /// Strongly-typed bindings that update the view from the model.
+ ///
+ module OneWayT =
+
+ /// Elemental instance of a one-way binding.
+ let id<'a, 'msg> : string -> Binding<'a, 'msg, 'a> = OneWay.id |> createBindingT
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt x : Binding<'a option, 'msg, System.Nullable<'a>> = x |> id |> mapModel Option.toNullable
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt x : Binding<'a voption, 'msg, System.Nullable<'a>> =
+ x |> id |> mapModel ValueOption.toNullable
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let optobj<'a, 'msg when 'a: null> : string -> Binding<'a option, 'msg, 'a> =
+ id<'a, 'msg> >> mapModel Option.toObj
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let voptobj<'a, 'msg when 'a: null> : string -> Binding<'a voption, 'msg, 'a> =
+ id<'a, 'msg> >> mapModel ValueOption.toObj
- module SubModel =
+ ///
+ /// Strongly-typed bindings that update the model from the view.
+ ///
+ module OneWayToSourceT =
+
+ /// Elemental instance of a one-way-to-source binding.
+ let id<'model, 'a> : string -> Binding<'model, 'a, 'a> =
+ OneWayToSource.id |> createBindingT
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let optobj<'a, 'model when 'a: null> : string -> Binding<'model, 'a option, 'a> =
+ id<'model, 'a> >> mapMsg Option.ofObj
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let voptobj<'a, 'model when 'a: null> : string -> Binding<'model, 'a voption, 'a> =
+ id<'model, 'a> >> mapMsg ValueOption.ofObj
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt x : Binding<'model, 'a option, System.Nullable<'a>> = x |> id |> mapMsg Option.ofNullable
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt x : Binding<'model, 'a voption, System.Nullable<'a>> =
+ x |> id |> mapMsg ValueOption.ofNullable
///
- /// Creates a binding to a sub-model/component. You typically bind this
- /// to the DataContext of a UserControl or similar.
+ /// Strongly-typed bindings that update both ways
///
- /// Returns the bindings for the sub-model.
- let vopt (bindings: unit -> Binding<'model, 'msg> list)
- : string -> Binding<'model voption, 'msg> =
- SubModel.create
- (fun args -> DynamicViewModel<'model, 'msg>(args, bindings ()))
- IViewModel.updateModel
- |> createBinding
+ module TwoWayT =
+
+ /// Elemental instance of a two-way binding.
+ let id<'a> : string -> Binding<'a, 'a, 'a> = TwoWay.id |> createBindingT
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt x : Binding<'a option, 'a option, System.Nullable<'a>> =
+ x
+ |> id
+ |> mapMsg Option.ofNullable
+ |> mapModel Option.toNullable
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt x : Binding<'a voption, 'a voption, System.Nullable<'a>> =
+ x
+ |> id
+ |> mapMsg ValueOption.ofNullable
+ |> mapModel ValueOption.toNullable
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let optobj<'a when 'a: null> : string -> Binding<'a option, 'a option, 'a> =
+ id<'a>
+ >> mapModel Option.toObj
+ >> mapMsg Option.ofObj
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let voptobj<'a when 'a: null> : string -> Binding<'a voption, 'a voption, 'a> =
+ id<'a>
+ >> mapMsg ValueOption.ofObj
+ >> mapModel ValueOption.toObj
///
- /// Creates a binding to a sub-model/component. You typically bind this
- /// to the DataContext of a UserControl or similar.
+ /// The strongly-typed counterpart of Binding.oneWaySeq with parameter getId.
+ /// Exposes an ObservableCollection of child items for binding.
+ /// Allows a more efficient update than would be possible without using ids.
///
- /// Returns the bindings for the sub-model.
- let opt (bindings: unit -> Binding<'model, 'msg> list)
- : string -> Binding<'model option, 'msg> =
- vopt bindings
- >> mapModel ValueOption.ofOption
+ module OneWaySeqT =
+
+ ///
+ /// Elemental instance of a OneWaySeqT binding
+ ///
+ /// Defines whether an item is "equal" and needs to be updated if the ids are the same
+ /// Unique identifier for each item in the list (for efficient updates).
+ let id itemEquals (getId: 'a -> 'id) : string -> Binding<_, 'msg, _> =
+ OneWaySeq.create itemEquals getId
+ |> createBindingT
///
- /// Creates a binding to a sub-model/component. You typically bind this
- /// to the DataContext of a UserControl or similar.
+ /// Strongly-typed bindings that dispatch messages from the view.
///
- /// Returns the bindings for the sub-model.
- let required (bindings: unit -> Binding<'model, 'msg> list)
- : string -> Binding<'model, 'msg> =
- vopt bindings
- >> mapModel ValueSome
-
- ///
- /// The strongly-typed counterpart of module SubModel.
- /// For creating bindings to child view models that have their own bindings.
- /// Typically bound from WPF using DataContext and Binding.
- /// Can be used in binding lists if boxed using .
- ///
- module SubModelT =
-
- /// Exposes an optional view model member for binding.
- let opt
- (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
- : (string -> Binding<'bindingModel voption, 'msg, #IViewModel<'bindingModel, 'msg>>)
- =
- SubModel.create createVm IViewModel.updateModel
- |> createBindingT
-
- /// Exposes a non-optional view model member for binding.
- let req
- (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
- : (string -> Binding<'bindingModel, 'msg, #IViewModel<'bindingModel, 'msg>>)
- =
- SubModel.create createVm IViewModel.updateModel
- |> createBindingT
- >> mapModel ValueSome
+ module CmdT =
+
+ ///
+ /// Elemental instance of a Command binding.
+ /// Creates a Command binding that only passes the CommandParameter)
+ ///
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ /// Indicates whether the command can execute.
+ let id<'model> uiBoundCmdParam canExec : string -> Binding<'model, obj, ICommand> =
+ Cmd.createWithParam (fun p _ -> ValueSome p) canExec uiBoundCmdParam
+ |> createBindingT
+
+ ///
+ /// Creates a Command binding that depends only on the model (not the
+ /// CommandParameter).
+ ///
+ /// Indicates whether the command can execute.
+ /// Returns the message to dispatch.
+ let model canExec (exec: 'model -> 'msg) : string -> Binding<'model, 'msg, ICommand> =
+ id false (fun _ m -> m |> canExec)
+ >> mapMsgWithModel (fun _ y -> y |> exec)
+ >> addLazy (fun m1 m2 -> canExec m1 = canExec m2)
+
+ ///
+ /// Creates a Command binding that dispatches the specified message.
+ ///
+ /// Indicates whether the command can execute.
+ /// The message to dispatch.
+ let set canExec (msg: 'msg) : string -> Binding<'model, 'msg, ICommand> =
+ id false (fun _ m -> m |> canExec) >> setMsg msg
+
+ ///
+ /// Creates a Command binding that depends only on the model (not the
+ /// CommandParameter) and always executes.
+ ///
+ /// Returns the message to dispatch.
+ let modelAlways (exec: 'model -> 'msg) : string -> Binding<'model, 'msg, ICommand> = model (fun _ -> true) exec
+
+ ///
+ /// Creates a Command binding that dispatches the specified message
+ /// and always executes.
+ ///
+ /// The message to dispatch.
+ let setAlways (msg: 'msg) : string -> Binding<'model, 'msg, ICommand> = set (fun _ -> true) msg
+
+ module OneWay =
+
+ /// Elemental instance of a one-way binding.
+ let id<'a, 'msg> : string -> Binding<'a, 'msg> = OneWay.id |> createBinding
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt<'a, 'msg> : string -> Binding<'a option, 'msg> =
+ id >> mapModel Option.box
+
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt<'a, 'msg> : string -> Binding<'a voption, 'msg> =
+ id >> mapModel ValueOption.box
+
+
+ module OneWayToSource =
+
+ /// Elemental instance of a one-way-to-source binding.
+ let id<'model, 'a> : string -> Binding<'model, 'a> =
+ OneWayToSource.id |> createBinding
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt<'model, 'a> : string -> Binding<'model, 'a voption> =
+ id<'model, obj> >> mapMsg ValueOption.unbox
+
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt<'model, 'a> : string -> Binding<'model, 'a option> =
+ id<'model, obj> >> mapMsg Option.unbox
+
+
+ module TwoWay =
+
+ /// Elemental instance of a two-way binding.
+ let id<'a> : string -> Binding<'a, 'a> = TwoWay.id |> createBinding
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let vopt<'a> : string -> Binding<'a voption, 'a voption> =
+ id
+ >> mapModel ValueOption.box
+ >> mapMsg ValueOption.unbox
+
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ let opt<'a> : string -> Binding<'a option, 'a option> =
+ id
+ >> mapModel Option.box
+ >> mapMsg Option.unbox
+
+
+ module SubModelSelectedItem =
+
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
+ let vopt subModelSeqBindingName : string -> Binding<'id voption, 'id voption> =
+ SubModelSelectedItem.create subModelSeqBindingName
+ |> createBinding
+ >> mapModel (ValueOption.map box)
+ >> mapMsg (ValueOption.map unbox)
+
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
+ let opt subModelSeqBindingName : string -> Binding<'id option, 'id option> =
+ vopt subModelSeqBindingName
+ >> mapModel ValueOption.ofOption
+ >> mapMsg ValueOption.toOption
+
+
+ module Cmd =
+
+ let internal createWithParam exec canExec autoRequery =
+ Cmd.createWithParam exec canExec autoRequery
+ |> createBinding
+
+ let internal create exec canExec =
+ createWithParam (fun _ -> exec) (fun _ -> canExec) false
+ >> addLazy (fun m1 m2 -> canExec m1 = canExec m2)
+
+
+ module OneWaySeq =
+
+ let internal create get itemEquals getId =
+ OneWaySeq.create itemEquals getId
+ |> BindingData.mapModel get
+ |> createBinding
+
+
+ module SubModel =
+
+ ///
+ /// Creates a binding to a sub-model/component. You typically bind this
+ /// to the DataContext of a UserControl or similar.
+ ///
+ /// Returns the bindings for the sub-model.
+ let vopt (bindings: unit -> Binding<'model, 'msg> list) : string -> Binding<'model voption, 'msg> =
+ SubModel.create (fun args -> DynamicViewModel<'model, 'msg>(args, bindings ())) IViewModel.updateModel
+ |> createBinding
+
+ ///
+ /// Creates a binding to a sub-model/component. You typically bind this
+ /// to the DataContext of a UserControl or similar.
+ ///
+ /// Returns the bindings for the sub-model.
+ let opt (bindings: unit -> Binding<'model, 'msg> list) : string -> Binding<'model option, 'msg> =
+ vopt bindings >> mapModel ValueOption.ofOption
+
+ ///
+ /// Creates a binding to a sub-model/component. You typically bind this
+ /// to the DataContext of a UserControl or similar.
+ ///
+ /// Returns the bindings for the sub-model.
+ let required (bindings: unit -> Binding<'model, 'msg> list) : string -> Binding<'model, 'msg> =
+ vopt bindings >> mapModel ValueSome
///
- /// Exposes a 'a seq (IEnumerable<'a>) view model member for binding.
- /// Used rarely; usually, you want to expose an ObservableCollection<'a>
- /// using SubModelSeqKeyedT or SubModelSeqUnkeyedT.
+ /// The strongly-typed counterpart of module SubModel.
+ /// For creating bindings to child view models that have their own bindings.
+ /// Typically bound from WPF using DataContext and Binding.
+ /// Can be used in binding lists if boxed using .
///
- let seq
- (createVm: ViewModelArgs<'bindingModel, 'msg> -> #seq<#IViewModel<'bindingModel, 'msg>>)
- : (string -> Binding<'bindingModel, 'msg, #seq<#IViewModel<'bindingModel, 'msg>>>)
- =
- SubModel.create createVm (fun (vms, m) -> vms |> Seq.iter (fun vm -> IViewModel.updateModel (vm, m)))
- |> createBindingT
- >> mapModel ValueSome
-
- ///
- /// The strongly-typed counterpart of Binding.subModelSeq without parameter getId.
- /// Exposes an ObservableCollection of child view models for binding.
- /// Identifies elements by index;
- /// if possible, use SubModelSeqKeyedT (which uses parameter getId) instead.
- /// Typically bound from WPF using DataContext and Binding.
- /// Can be used in binding lists if boxed using .
- ///
- module SubModelSeqUnkeyedT =
+ module SubModelT =
+
+ /// Exposes an optional view model member for binding.
+ let opt
+ (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
+ : (string -> Binding<'bindingModel voption, 'msg, #IViewModel<'bindingModel, 'msg>>) =
+ SubModel.create createVm IViewModel.updateModel
+ |> createBindingT
+
+ /// Exposes a non-optional view model member for binding.
+ let req
+ (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
+ : (string -> Binding<'bindingModel, 'msg, #IViewModel<'bindingModel, 'msg>>) =
+ SubModel.create createVm IViewModel.updateModel
+ |> createBindingT
+ >> mapModel ValueSome
+
+ ///
+ /// Exposes a 'a seq (IEnumerable<'a>) view model member for binding.
+ /// Used rarely; usually, you want to expose an ObservableCollection<'a>
+ /// using SubModelSeqKeyedT or SubModelSeqUnkeyedT.
+ ///
+ let seq
+ (createVm: ViewModelArgs<'bindingModel, 'msg> -> #seq<#IViewModel<'bindingModel, 'msg>>)
+ : (string -> Binding<'bindingModel, 'msg, #seq<#IViewModel<'bindingModel, 'msg>>>) =
+ SubModel.create createVm (fun (vms, m) ->
+ vms
+ |> Seq.iter (fun vm -> IViewModel.updateModel (vm, m)))
+ |> createBindingT
+ >> mapModel ValueSome
///
- /// Creates an elemental SubModelSeqUnkeyedT binding.
+ /// The strongly-typed counterpart of Binding.subModelSeq without parameter getId.
+ /// Exposes an ObservableCollection of child view models for binding.
+ /// Identifies elements by index;
+ /// if possible, use SubModelSeqKeyedT (which uses parameter getId) instead.
+ /// Typically bound from WPF using DataContext and Binding.
+ /// Can be used in binding lists if boxed using .
///
- ///
- /// The function applied to every element of the bound ObservableCollection
- /// to create a child view model.
- ///
- let id
- (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
- : (string -> Binding<'bindingModelCollection, int * 'msg, ObservableCollection<#IViewModel<'bindingModel, 'msg>>>)
- =
- SubModelSeqUnkeyed.create createVm IViewModel.updateModel
- |> createBindingT
-
- ///
- /// The strongly-typed counterpart of Binding.subModelSeq with parameter getId.
- /// Exposes an ObservableCollection of child view models for binding.
- /// Typically bound from WPF using DataContext and Binding.
- /// Can be used in binding lists if boxed using .
- ///
- module SubModelSeqKeyedT =
+ module SubModelSeqUnkeyedT =
+
+ ///
+ /// Creates an elemental SubModelSeqUnkeyedT binding.
+ ///
+ ///
+ /// The function applied to every element of the bound ObservableCollection
+ /// to create a child view model.
+ ///
+ let id
+ (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
+ : (string -> Binding<'bindingModelCollection, int * 'msg, ObservableCollection<#IViewModel<'bindingModel, 'msg>>>) =
+ SubModelSeqUnkeyed.create createVm IViewModel.updateModel
+ |> createBindingT
///
- /// Creates an elemental SubModelSeqUnkeyedT binding.
+ /// The strongly-typed counterpart of Binding.subModelSeq with parameter getId.
+ /// Exposes an ObservableCollection of child view models for binding.
+ /// Typically bound from WPF using DataContext and Binding.
+ /// Can be used in binding lists if boxed using .
///
- ///
- /// The function applied to every element of the bound ObservableCollection
- /// to create a child view model.
- ///
- ///
- /// The function applied to every element of the bound ObservableCollection
- /// to get a key used to identify that element.
- /// Should not return duplicate keys for different elements.
- ///
- let id
- (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
- (getId: 'bindingModel -> 'id)
- : (string -> Binding<'bindingModelCollection, 'id * 'msg, ObservableCollection<#IViewModel<'bindingModel, 'msg>>>)
- =
- SubModelSeqKeyed.create createVm IViewModel.updateModel getId (IViewModel.currentModel >> getId)
- |> createBindingT
-
- ///
- /// The strongly-typed counterpart of Binding.subModelWin.
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (either in code
- /// or in XAML).
- ///
- /// Can be used in binding lists if boxed using .
- ///
- module SubModelWinT =
+ module SubModelSeqKeyedT =
+
+ ///
+ /// Creates an elemental SubModelSeqUnkeyedT binding.
+ ///
+ ///
+ /// The function applied to every element of the bound ObservableCollection
+ /// to create a child view model.
+ ///
+ ///
+ /// The function applied to every element of the bound ObservableCollection
+ /// to get a key used to identify that element.
+ /// Should not return duplicate keys for different elements.
+ ///
+ let id
+ (createVm: ViewModelArgs<'bindingModel, 'msg> -> #IViewModel<'bindingModel, 'msg>)
+ (getId: 'bindingModel -> 'id)
+ : (string -> Binding<'bindingModelCollection, 'id * 'msg, ObservableCollection<#IViewModel<'bindingModel, 'msg>>>) =
+ SubModelSeqKeyed.create createVm IViewModel.updateModel getId (IViewModel.currentModel >> getId)
+ |> createBindingT
///
- /// Creates an elemental SubModelWinT binding.
+ /// The strongly-typed counterpart of Binding.subModelWin.
/// Like , but uses the WindowState wrapper
/// to show/hide/close a new window that will have the specified bindings as
/// its DataContext.
///
/// You do not need to set the DataContext yourself (either in code
/// or in XAML).
- /// The window can only be closed/hidden by changing the return value of
- /// , and cannot be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it
- /// or displaying relevant feedback to the user).
+ ///
+ /// Can be used in binding lists if boxed using .
///
- /// Gets the window state and a sub-model.
- /// Returns the view model for the window.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// Window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// Window.Show).
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- let id
- (getState: 'model -> WindowState<'bindingModel>)
- (createVM: ViewModelArgs<'bindingModel, 'bindingMsg> -> #IViewModel<'bindingModel, 'bindingMsg>)
- getWindow isModal onCloseRequested =
- SubModelWin.create getState createVM IViewModel.updateModel Func2.id2 getWindow isModal onCloseRequested
- |> createBindingT
-
+ module SubModelWinT =
+
+ ///
+ /// Creates an elemental SubModelWinT binding.
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (either in code
+ /// or in XAML).
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and cannot be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it
+ /// or displaying relevant feedback to the user).
+ ///
+ /// Gets the window state and a sub-model.
+ /// Returns the view model for the window.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// Window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// Window.Show).
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ let id
+ (getState: 'model -> WindowState<'bindingModel>)
+ (createVM: ViewModelArgs<'bindingModel, 'bindingMsg> -> #IViewModel<'bindingModel, 'bindingMsg>)
+ getWindow
+ isModal
+ onCloseRequested
+ =
+ SubModelWin.create getState createVM IViewModel.updateModel Func2.id2 getWindow isModal onCloseRequested
+ |> createBindingT
+
+
+ module SelectedIndex =
+ /// Prebuilt binding intended for use with Selector.SelectedIndex.
+ let vopt =
+ TwoWay.id
+ >> mapModel (ValueOption.defaultValue -1)
+ >> mapMsg (fun i -> if i < 0 then ValueNone else ValueSome i)
+
+ /// Prebuilt binding intended for use with Selector.SelectedIndex.
+ let opt =
+ vopt
+ >> mapModel ValueOption.ofOption
+ >> mapMsg ValueOption.toOption
+
+
+ module SubModelWin =
+
+ let internal create getState createViewModel updateViewModel toMsg getWindow isModal onCloseRequested =
+ SubModelWin.create getState createViewModel updateViewModel toMsg getWindow isModal onCloseRequested
+ |> createBinding
+
+
+ module SubModelSeqUnkeyed =
+
+ let internal create createViewModel updateViewModel =
+ SubModelSeqUnkeyed.create createViewModel updateViewModel
+ |> createBinding
+
+
+ module SubModelSeqKeyed =
+
+ let internal create createViewModel updateViewModel bmToId vmToId =
+ SubModelSeqKeyed.create createViewModel updateViewModel bmToId vmToId
+ |> createBinding
- module SelectedIndex =
- /// Prebuilt binding intended for use with Selector.SelectedIndex.
- let vopt =
- TwoWay.id
- >> mapModel (ValueOption.defaultValue -1)
- >> mapMsg (fun i -> if i < 0 then ValueNone else ValueSome i)
-
- /// Prebuilt binding intended for use with Selector.SelectedIndex.
- let opt =
- vopt
- >> mapModel ValueOption.ofOption
- >> mapMsg ValueOption.toOption
+module Bindings =
- module SubModelWin =
+ /// Maps the model of a list of bindings via a contravariant mapping.
+ let mapModel (f: 'a -> 'b) (bindings: Binding<'b, 'msg> list) =
+ f |> Binding.mapModel |> List.map <| bindings
- let internal create getState createViewModel updateViewModel toMsg getWindow isModal onCloseRequested =
- SubModelWin.create getState createViewModel updateViewModel toMsg getWindow isModal onCloseRequested
- |> createBinding
+ /// Maps the message of a list of bindings with access to the model via a covariant mapping.
+ let mapMsgWithModel (f: 'a -> 'model -> 'b) (bindings: Binding<'model, 'a> list) =
+ f |> Binding.mapMsgWithModel |> List.map
+ <| bindings
+ /// Maps the message of a list of bindings via a covariant mapping.
+ let mapMsg (f: 'a -> 'b) (bindings: Binding<'model, 'a> list) =
+ f |> Binding.mapMsg |> List.map <| bindings
- module SubModelSeqUnkeyed =
- let internal create createViewModel updateViewModel =
- SubModelSeqUnkeyed.create createViewModel updateViewModel
- |> createBinding
+[]
+type Binding private () =
+ ///
+ /// Creates a binding intended for use with Selector.SelectedIndex.
+ ///
+ /// Gets the selected index from the model.
+ /// Returns the message to dispatch.
+ static member selectedIndex(get: 'model -> int voption, set: int voption -> 'msg) =
+ Binding.SelectedIndex.vopt
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
- module SubModelSeqKeyed =
+ ///
+ /// Creates a binding intended for use with Selector.SelectedIndex.
+ ///
+ /// Gets the selected index from the model.
+ /// Returns the message to dispatch.
+ static member selectedIndex(get: 'model -> int option, set: int option -> 'msg) =
+ Binding.SelectedIndex.opt
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
- let internal create createViewModel updateViewModel bmToId vmToId =
- SubModelSeqKeyed.create createViewModel updateViewModel bmToId vmToId
- |> createBinding
+ /// Creates a one-way binding.
+ /// Gets the value from the model.
+ static member oneWay(get: 'model -> 'a) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.id<'a, 'msg>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
-module Bindings =
- /// Maps the model of a list of bindings via a contravariant mapping.
- let mapModel (f: 'a -> 'b) (bindings: Binding<'b, 'msg> list) = f |> Binding.mapModel |> List.map <| bindings
+ ///
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ static member oneWayOpt(get: 'model -> 'a option) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.opt<'a, 'msg>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
- /// Maps the message of a list of bindings with access to the model via a covariant mapping.
- let mapMsgWithModel (f: 'a -> 'model -> 'b) (bindings: Binding<'model, 'a> list) = f |> Binding.mapMsgWithModel |> List.map <| bindings
- /// Maps the message of a list of bindings via a covariant mapping.
- let mapMsg (f: 'a -> 'b) (bindings: Binding<'model, 'a> list) = f |> Binding.mapMsg |> List.map <| bindings
+ ///
+ /// Creates a one-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ static member oneWayOpt(get: 'model -> 'a voption) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.vopt<'a, 'msg>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
-[]
-type Binding private () =
+ ///
+ /// Creates a lazily evaluated one-way binding.
+ /// will be called only when the output of changes,
+ /// as determined by . This may have better
+ /// performance than for expensive computations (but
+ /// may be less performant for non-expensive functions due to additional
+ /// overhead).
+ ///
+ /// Gets the value from the model.
+ ///
+ /// Indicates whether two intermediate values are equal. Good candidates are
+ /// elmEq and refEq.
+ ///
+ /// Transforms the value into the final type.
+ static member oneWayLazy
+ (
+ get: 'model -> 'a,
+ equals: 'a -> 'a -> bool,
+ map: 'a -> 'b
+ ) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.id<'b, 'msg>
+ >> Binding.mapModel map
+ >> Binding.addLazy equals
+ >> Binding.mapModel get
+ >> Binding.addCaching
- ///
- /// Creates a binding intended for use with Selector.SelectedIndex.
- ///
- /// Gets the selected index from the model.
- /// Returns the message to dispatch.
- static member selectedIndex
- (get: 'model -> int voption,
- set: int voption -> 'msg) =
- Binding.SelectedIndex.vopt
- >> Binding.mapModel get
- >> Binding.mapMsg set
-
- ///
- /// Creates a binding intended for use with Selector.SelectedIndex.
- ///
- /// Gets the selected index from the model.
- /// Returns the message to dispatch.
- static member selectedIndex
- (get: 'model -> int option,
- set: int option -> 'msg) =
- Binding.SelectedIndex.opt
- >> Binding.mapModel get
- >> Binding.mapMsg set
-
-
- /// Creates a one-way binding.
- /// Gets the value from the model.
- static member oneWay
- (get: 'model -> 'a)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.id<'a, 'msg>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
-
-
- ///
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly
- /// null) value on the view side.
- ///
- /// Gets the value from the model.
- static member oneWayOpt
- (get: 'model -> 'a option)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.opt<'a, 'msg>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
-
-
- ///
- /// Creates a one-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly
- /// null) value on the view side.
- ///
- /// Gets the value from the model.
- static member oneWayOpt
- (get: 'model -> 'a voption)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.vopt<'a, 'msg>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
-
-
- ///
- /// Creates a lazily evaluated one-way binding.
- /// will be called only when the output of changes,
- /// as determined by . This may have better
- /// performance than for expensive computations (but
- /// may be less performant for non-expensive functions due to additional
- /// overhead).
- ///
- /// Gets the value from the model.
- ///
- /// Indicates whether two intermediate values are equal. Good candidates are
- /// elmEq and refEq.
- ///
- /// Transforms the value into the final type.
- static member oneWayLazy
- (get: 'model -> 'a,
- equals: 'a -> 'a -> bool,
- map: 'a -> 'b)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.id<'b, 'msg>
- >> Binding.mapModel map
- >> Binding.addLazy equals
- >> Binding.mapModel get
- >> Binding.addCaching
-
-
- ///
- /// Creates a lazily evaluated one-way binding to an optional value. The
- /// binding automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side. will be called only when the output of changes, as determined by .
- ///
- /// This may have better performance than a non-lazy binding for expensive
- /// computations (but may be less performant for non-expensive functions due
- /// to additional overhead).
- ///
- /// Gets the intermediate value from the model.
- ///
- /// Indicates whether two intermediate values are equal. Good candidates are
- /// elmEq and refEq.
- ///
- /// Transforms the intermediate value into the final
- /// type.
- static member oneWayOptLazy
- (get: 'model -> 'a,
- equals: 'a -> 'a -> bool,
- map: 'a -> 'b option)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.opt<'b, 'msg>
- >> Binding.mapModel map
- >> Binding.addLazy equals
- >> Binding.mapModel get
- >> Binding.addCaching
-
-
- ///
- /// Creates a lazily evaluated one-way binding to an optional value. The
- /// binding automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side. will be called only when the output of changes, as determined by .
- ///
- /// This may have better performance than a non-lazy binding for expensive
- /// computations (but may be less performant for non-expensive functions due
- /// to additional overhead).
- ///
- /// Gets the value from the model.
- ///
- /// Indicates whether two intermediate values are equal. Good candidates are
- /// elmEq and refEq.
- ///
- /// Transforms the intermediate value into the final
- /// type.
- static member oneWayOptLazy
- (get: 'model -> 'a,
- equals: 'a -> 'a -> bool,
- map: 'a -> 'b voption)
- : string -> Binding<'model, 'msg> =
- Binding.OneWay.vopt<'b, 'msg>
- >> Binding.mapModel map
- >> Binding.addLazy equals
- >> Binding.mapModel get
- >> Binding.addCaching
-
-
- /// Creates a one-way-to-source binding.
- /// Returns the message to dispatch.
- static member oneWayToSource
- (set: 'a -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.id<'model, 'a>
- >> Binding.mapMsgWithModel set
-
- ///
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- ///
- /// Returns the message to dispatch.
- static member oneWayToSourceOpt
- (set: 'a option -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.opt
- >> Binding.mapMsgWithModel set
-
- ///
- /// Creates a one-way-to-source binding to an optional value. The binding
- /// automatically converts between a missing value in the model and
- /// a null value in the view.
- ///
- /// Returns the message to dispatch.
- static member oneWayToSourceOpt
- (set: 'a voption -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.vopt
- >> Binding.mapMsgWithModel set
-
-
- ///
- /// Creates a one-way binding to a sequence of items, each uniquely
- /// identified by the value returned by . The
- /// binding will not be updated if the output of
- /// does not change, as determined by .
- /// The binding is backed by a persistent ObservableCollection, so
- /// only changed items (as determined by )
- /// will be replaced. If the items are complex and you want them updated
- /// instead of replaced, consider using .
- ///
- /// Gets the intermediate value from the model.
- ///
- /// Indicates whether two intermediate values are equal. Good candidates are
- /// elmEq and refEq.
- ///
- /// Transforms the value into the final collection.
- ///
- /// Indicates whether two collection items are equal. Good candidates are
- /// elmEq, refEq, or simply (=).
- ///
- /// Gets a unique identifier for a collection
- /// item.
- static member oneWaySeqLazy
- (get: 'model -> 'a,
- equals: 'a -> 'a -> bool,
- map: 'a -> #seq<'b>,
- itemEquals: 'b -> 'b -> bool,
- getId: 'b -> 'id)
- : string -> Binding<'model, 'msg> =
- Binding.OneWaySeq.create map itemEquals getId
- >> Binding.addLazy equals
- >> Binding.mapModel get
-
-
- ///
- /// Creates a one-way binding to a sequence of items, each uniquely
- /// identified by the value returned by . The
- /// binding will not be updated if the output of
- /// is referentially equal. This is the same as calling
- /// with equals = refEq and
- /// map = id. The binding is backed by a persistent
- /// ObservableCollection, so only changed items (as determined by
- /// ) will be replaced. If the items are
- /// complex and you want them updated instead of replaced, consider using
- /// .
- ///
- /// Gets the collection from the model.
- ///
- /// Indicates whether two collection items are equal. Good candidates are
- /// elmEq, refEq, or simply (=).
- ///
- /// Gets a unique identifier for a collection
- /// item.
- static member oneWaySeq
- (get: 'model -> #seq<'a>,
- itemEquals: 'a -> 'a -> bool,
- getId: 'a -> 'id)
- : string -> Binding<'model, 'msg> =
- Binding.OneWaySeq.create id itemEquals getId
- >> Binding.addLazy refEq
- >> Binding.mapModel get
-
-
- /// Creates a two-way binding.
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- static member twoWay
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
-
- /// Creates a two-way binding.
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWay
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWay (get, set)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- static member twoWayOpt
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
-
- ///
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOpt
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOpt (get, set)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- static member twoWayOpt
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
-
- ///
- /// Creates a two-way binding to an optional value. The binding
- /// automatically converts between the optional source value and an
- /// unwrapped (possibly null) value on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOpt
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOpt (get, set)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation validate
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> Option.toList)
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding with validation using
- /// INotifyDataErrorInfo.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation validate
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> Option.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation validate
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation messages from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> Option.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
-
- ///
- /// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts between
- /// the optional source value and an unwrapped (possibly null) value
- /// on the view side.
- ///
- /// Gets the value from the model.
- /// Returns the message to dispatch.
- ///
- /// Returns the validation message from the updated model.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'model -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a Command binding that depends only on the model (not the
- /// CommandParameter) and can always execute.
- ///
- /// Returns the message to dispatch.
- static member cmd
- (exec: 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (exec >> ValueSome)
- (fun _ -> true)
-
- ///
- /// Creates a Command binding that depends only on the model (not the
- /// CommandParameter) and can always execute.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmd
- (exec: 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmd exec
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns true.
- ///
- /// Returns the message to dispatch.
- /// Indicates whether the command can execute.
- static member cmdIf
- (exec: 'model -> 'msg,
- canExec: 'model -> bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (exec >> ValueSome)
- canExec
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns true.
- ///
- /// Returns the message to dispatch.
- /// Indicates whether the command can execute.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdIf
- (exec: 'model -> 'msg,
- canExec: 'model -> bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdIf (exec, canExec)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns ValueSome.
- ///
- /// Returns the message to dispatch.
- static member cmdIf
- (exec: 'model -> 'msg voption)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- exec
- (exec >> ValueOption.isSome)
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns ValueSome.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdIf
- (exec: 'model -> 'msg voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdIf exec
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns Some.
- ///
- /// Returns the message to dispatch.
- static member cmdIf
- (exec: 'model -> 'msg option)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (exec >> ValueOption.ofOption)
- (exec >> Option.isSome)
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns Some.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdIf
- (exec: 'model -> 'msg option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdIf exec
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns Ok.
- ///
- /// This overload allows more easily re-using the same validation functions
- /// for inputs and commands.
- ///
- /// Returns the message to dispatch.
- static member cmdIf
- (exec: 'model -> Result<'msg, 'ignored>)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (exec >> ValueOption.ofOk)
- (exec >> Result.isOk)
-
- ///
- /// Creates a conditional Command binding that depends only on the
- /// model (not the CommandParameter) and can execute if
- /// returns Ok.
- ///
- /// This overload allows more easily re-using the same validation functions
- /// for inputs and commands.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdIf
- (exec: 'model -> Result<'msg, 'ignored>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdIf exec
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a Command binding that depends on the
- /// CommandParameter
- /// and can always execute.
- ///
- /// Returns the message to dispatch.
- static member cmdParam
- (exec: obj -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p model -> exec p model |> ValueSome)
- (fun _ _ -> true)
- false
-
- ///
- /// Creates a Command binding that depends on the
- /// CommandParameter
- /// and can always execute.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParam
- (exec: obj -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParam exec
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns true.
- ///
- /// Returns the message to dispatch.
- /// Indicates whether the command can execute.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg,
- canExec: obj -> 'model -> bool,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p m -> exec p m |> ValueSome)
- canExec
- (defaultArg uiBoundCmdParam false)
-
- ///
- /// Creates a Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns true.
- ///
- /// Returns the message to dispatch.
- /// Indicates whether the command can execute.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg,
- canExec: obj -> 'model -> bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, canExec)
- >> Binding.alterMsgStream wrapDispatch
-
- ///
- /// Creates a Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns true.
- ///
- /// Returns the message to dispatch.
- /// Indicates whether the command can execute.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg,
- canExec: obj -> 'model -> bool,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, canExec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns ValueSome.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg voption,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- exec
- (fun p m -> exec p m |> ValueOption.isSome)
- (defaultArg uiBoundCmdParam false)
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns ValueSome.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns ValueSome.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg voption,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Some.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg option,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p m -> exec p m |> ValueOption.ofOption)
- (fun p m -> exec p m |> Option.isSome)
- (defaultArg uiBoundCmdParam false)
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Some.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Some.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> 'msg option,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation functions
- /// for inputs and commands.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- static member cmdParamIf
- (exec: obj -> 'model -> Result<'msg, 'ignored>,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p m -> exec p m |> ValueOption.ofOk)
- (fun p m -> exec p m |> Result.isOk)
- (defaultArg uiBoundCmdParam false)
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation functions
- /// for inputs and commands.
- ///
- /// Returns the message to dispatch.
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> Result<'msg, 'ignored>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
-
- ///
- /// Creates a conditional Command binding that depends on the
- /// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation functions
- /// for inputs and commands.
- ///
- /// Returns the message to dispatch.
- ///
- /// If true, CanExecuteChanged will trigger every time WPF's
- /// CommandManager
- /// detects UI changes that could potentially influence the command's
- /// ability to execute. This will likely lead to many more triggers than
- /// necessary, but is needed if you have bound the CommandParameter
- /// to another UI property.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member cmdParamIf
- (exec: obj -> 'model -> Result<'msg, 'ignored>,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- []
- static member subModel
- (getSubModel: 'model -> 'subModel,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- toMsg: 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.required bindings
- >> Binding.mapModel (fun m -> toBindingModel (m, getSubModel m))
- >> Binding.mapMsg toMsg
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- []
- static member subModel
- (getSubModel: 'model -> 'subModel,
- toMsg: 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.required bindings
- >> Binding.mapModel (fun m -> (m, getSubModel m))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings.
- /// You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// Gets the sub-model from the model.
- /// Returns the bindings for the sub-model.
- [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with its implementation.")>]
- static member subModel
- (getSubModel: 'model -> 'subModel,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.required bindings
- >> Binding.mapModel (fun m -> (m, getSubModel m))
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type, and may not exist. If it does not exist, bindings to this
- /// model will return null unless is
- /// true, in which case the last non-null model will be
- /// returned. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- []
- static member subModelOpt
- (getSubModel: 'model -> 'subModel voption,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- toMsg: 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.vopt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> ValueOption.map (fun sub -> toBindingModel (m, sub)))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type, and may not exist. If it does not exist, bindings to this
- /// model will return null unless is
- /// true, in which case the last non-null model will be
- /// returned. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- []
- static member subModelOpt
- (getSubModel: 'model -> 'subModel option,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- toMsg: 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.opt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> Option.map (fun sub -> toBindingModel (m, sub)))
- >> Binding.mapMsg toMsg
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type, and may not exist. If it does not exist, bindings to this
- /// model will return null unless is
- /// true, in which case the last non-null model will be
- /// returned. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- []
- static member subModelOpt
- (getSubModel: 'model -> 'subModel voption,
- toMsg: 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.vopt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> ValueOption.map (fun sub -> (m, sub)))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings and
- /// message type, and may not exist. If it does not exist, bindings to this
- /// model will return null unless is
- /// true, in which case the last non-null model will be
- /// returned. You typically bind this to the DataContext of a
- /// UserControl or similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- []
- static member subModelOpt
- (getSubModel: 'model -> 'subModel option,
- toMsg: 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.opt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> Option.map (fun sub -> (m, sub)))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings,
- /// and may not exist. If it does not exist, bindings to this model will
- /// return null unless is true, in
- /// which case the last non-null model will be returned. You
- /// typically bind this to the DataContext of a UserControl or
- /// similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with (a specialization of) its implementation.")>]
- static member subModelOpt
- (getSubModel: 'model -> 'subModel voption,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.vopt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> ValueOption.map (fun sub -> (m, sub)))
-
-
- ///
- /// Creates a binding to a sub-model/component that has its own bindings,
- /// and may not exist. If it does not exist, bindings to this model will
- /// return null unless is true, in
- /// which case the last non-null model will be returned. You
- /// typically bind this to the DataContext of a UserControl or
- /// similar.
- ///
- /// The 'sticky' part is useful if you want to e.g. animate away a
- /// UserControl when the model is missing, but don't want the data
- /// used by that control to be cleared once the animation starts. (The
- /// animation must be triggered using another binding since this will never
- /// return null.)
- ///
- /// Gets the sub-model from the model.
- /// Returns the bindings for the sub-model.
- ///
- /// If true, when the model is missing, the last non-null
- /// model will be returned instead of null.
- ///
- [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with (a specialization of) its implementation.")>]
- static member subModelOpt
- (getSubModel: 'model -> 'subModel option,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list,
- ?sticky: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModel.opt bindings
- >> if (defaultArg sticky false) then Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone) else id
- >> Binding.mapModel (fun m -> getSubModel m |> Option.map (fun sub -> (m, sub)))
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// If you don't need a sub-model, you can use
- /// WindowState<unit> to just control the Window visibility,
- /// and pass fst to .
- ///
- /// Gets the window state and a sub-model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- toMsg: 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
- getWindow: 'model -> Dispatch<'msg> -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelWin.create
- (fun m -> getState m |> WindowState.map (fun sub -> toBindingModel (m, sub)))
- (fun args -> DynamicViewModel<'bindingModel, 'bindingMsg>(args, bindings ()))
- IViewModel.updateModel
- (fun _ -> toMsg)
- (fun m d -> upcast getWindow m d)
- (defaultArg isModal false)
- (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// If you don't need a sub-model, you can use
- /// WindowState<unit> to just control the Window visibility,
- /// and pass fst to .
- ///
- /// Gets the window state and a sub-model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- toMsg: 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
- getWindow: unit -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.subModelWin(
- getState,
- toBindingModel,
- toMsg,
- bindings,
- (fun _ _ -> getWindow ()),
- ?onCloseRequested = onCloseRequested,
- ?isModal = isModal
- )
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// Gets the window state and a sub-model.
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- toMsg: 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
- getWindow: 'model -> Dispatch<'msg> -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelWin.create
- (fun m -> getState m |> WindowState.map (fun sub -> (m, sub)))
- (fun args -> DynamicViewModel<'model * 'subModel, 'subMsg>(args, bindings ()))
- IViewModel.updateModel
- (fun _ -> toMsg)
- (fun m d -> upcast getWindow m d)
- (defaultArg isModal false)
- (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// Gets the window state and a sub-model.
- ///
- /// Converts the messages used in the bindings to parent model messages
- /// (e.g. a parent message union case that wraps the child message type).
- ///
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- toMsg: 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
- getWindow: unit -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.subModelWin(
- getState,
- toMsg,
- bindings,
- (fun _ _ -> getWindow ()),
- ?onCloseRequested = onCloseRequested,
- ?isModal = isModal
- )
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// Gets the window state and a sub-model.
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list,
- getWindow: 'model -> Dispatch<'msg> -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelWin.create
- (fun m -> getState m |> WindowState.map (fun sub -> (m, sub)))
- (fun args -> DynamicViewModel<'model * 'subModel, 'msg>(args, bindings ()))
- IViewModel.updateModel
- (fun _ -> id)
- (fun m d -> upcast getWindow m d)
- (defaultArg isModal false)
- (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
-
-
- ///
- /// Like , but uses the WindowState wrapper
- /// to show/hide/close a new window that will have the specified bindings as
- /// its DataContext.
- ///
- /// You do not need to set the DataContext yourself (neither in code
- /// nor XAML).
- ///
- /// The window can only be closed/hidden by changing the return value of
- /// , and can not be directly closed by the
- /// user. External close attempts (the Close/X button, Alt+F4, or System
- /// Menu -> Close) will cause the message specified by
- /// to be dispatched. You should supply
- /// and react to this in a manner that
- /// will not confuse a user trying to close the window (e.g. by closing it,
- /// or displaying relevant feedback to the user.)
- ///
- /// Gets the window state and a sub-model.
- /// Returns the bindings for the sub-model.
- ///
- /// The function used to get and configure the window.
- ///
- ///
- /// The message to be dispatched on external close attempts (the Close/X
- /// button, Alt+F4, or System Menu -> Close).
- ///
- ///
- /// Specifies whether the window will be shown modally (using
- /// window.ShowDialog, blocking the rest of the app) or non-modally (using
- /// window.Show).
- ///
- static member subModelWin
- (getState: 'model -> WindowState<'subModel>,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list,
- getWindow: unit -> #Window,
- ?onCloseRequested: 'msg,
- ?isModal: bool)
- : string -> Binding<'model, 'msg> =
- Binding.subModelWin(
- getState,
- bindings,
- (fun _ _ -> getWindow ()),
- ?onCloseRequested = onCloseRequested,
- ?isModal = isModal
- )
-
- static member subModelSeq // TODO: make into function
- (getBindings: unit -> Binding<'model, 'msg> list)
- : string -> Binding<'model seq, int * 'msg> =
- Binding.SubModelSeqUnkeyed.create
- (fun args -> DynamicViewModel<'model, 'msg>(args, getBindings ()))
- IViewModel.updateModel
-
- static member subModelSeq // TODO: make into function
- (getBindings: unit -> Binding<'model, 'msg> list,
- getId: 'model -> 'id)
- : string -> Binding<'model seq, 'id * 'msg> =
- Binding.SubModelSeqKeyed.create
- (fun args -> DynamicViewModel<'model, 'msg>(args, getBindings ()))
- IViewModel.updateModel
- getId
- (IViewModel.currentModel >> getId)
-
-
- ///
- /// Creates a binding to a sequence of sub-models, each uniquely identified
- /// by the value returned by . The sub-models have
- /// their own bindings and message type. You typically bind this to the
- /// ItemsSource of an ItemsControl, ListView,
- /// TreeView, etc.
- ///
- /// Gets the sub-models from the model.
- ///
- /// Converts the models to the model used by the bindings.
- ///
- /// Gets a unique identifier for a sub-model.
- ///
- /// Converts the sub-model ID and messages used in the bindings to parent
- /// model messages (e.g. a parent message union case that wraps the
- /// sub-model ID and message type).
- ///
- /// Returns the bindings for the sub-model.
- static member subModelSeq
- (getSubModels: 'model -> #seq<'subModel>,
- toBindingModel: 'model * 'subModel -> 'bindingModel,
- getId: 'bindingModel -> 'id,
- toMsg: 'id * 'bindingMsg -> 'msg,
- bindings: unit -> Binding<'bindingModel, 'bindingMsg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSeqKeyed.create
- (fun args -> DynamicViewModel<'bindingModel, 'bindingMsg>(args, bindings ()))
- IViewModel.updateModel
- getId
- (IViewModel.currentModel >> getId)
- >> Binding.mapModel (fun m -> getSubModels m |> Seq.map (fun sub -> toBindingModel (m, sub)))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sequence of sub-models, each uniquely identified
- /// by the value returned by . The sub-models have
- /// their own bindings and message type. You typically bind this to the
- /// ItemsSource of an ItemsControl, ListView,
- /// TreeView, etc.
- ///
- /// Gets the sub-models from the model.
- /// Gets a unique identifier for a sub-model.
- ///
- /// Converts the sub-model ID and messages used in the bindings to parent
- /// model messages (e.g. a parent message union case that wraps the
- /// sub-model ID and message type).
- ///
- /// Returns the bindings for the sub-model.
- static member subModelSeq
- (getSubModels: 'model -> #seq<'subModel>,
- getId: 'subModel -> 'id,
- toMsg: 'id * 'subMsg -> 'msg,
- bindings: unit -> Binding<'model * 'subModel, 'subMsg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSeqKeyed.create
- (fun args -> DynamicViewModel<'model * 'subModel, 'subMsg>(args, bindings ()))
- IViewModel.updateModel
- (snd >> getId)
- (IViewModel.currentModel >> snd >> getId)
- >> Binding.mapModel (fun m -> getSubModels m |> Seq.map (fun sub -> (m, sub)))
- >> Binding.mapMsg toMsg
-
-
- ///
- /// Creates a binding to a sequence of sub-models, each uniquely identified
- /// by the value returned by . The sub-models have
- /// their own bindings. You typically bind this to the ItemsSource of
- /// an
- /// ItemsControl, ListView, TreeView, etc.
- ///
- /// Gets the sub-models from the model.
- /// Gets a unique identifier for a sub-model.
- /// Returns the bindings for the sub-model.
- static member subModelSeq
- (getSubModels: 'model -> #seq<'subModel>,
- getId: 'subModel -> 'id,
- bindings: unit -> Binding<'model * 'subModel, 'msg> list)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSeqKeyed.create
- (fun args -> DynamicViewModel<'model * 'subModel, 'msg>(args, bindings ()))
- IViewModel.updateModel
- (snd >> getId)
- (IViewModel.currentModel >> snd >> getId)
- >> Binding.mapModel (fun m -> getSubModels m |> Seq.map (fun sub -> (m, sub)))
- >> Binding.mapMsg snd
-
-
- ///
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the
- /// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
- ///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or
- /// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- ///
- ///
- /// The name of the binding used as the items
- /// source.
- ///
- /// Gets the selected sub-model/sub-binding ID from the
- /// model.
- ///
- /// Returns the message to dispatch on selections/de-selections.
- ///
- static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id voption,
- set: 'id voption -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSelectedItem.vopt subModelSeqBindingName
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addCaching
-
- ///
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the
- /// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
- ///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or
- /// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- ///
- ///
- /// The name of the binding used as the items
- /// source.
- ///
- /// Gets the selected sub-model/sub-binding ID from the
- /// model.
- ///
- /// Returns the message to dispatch on selections/de-selections.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id voption,
- set: 'id voption -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
- >> Binding.alterMsgStream wrapDispatch
-
-
- ///
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the
- /// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
- ///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or
- /// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- ///
- ///
- /// The name of the binding used as the items
- /// source.
- ///
- /// Gets the selected sub-model/sub-binding ID from the
- /// model.
- ///
- /// Returns the message to dispatch on selections/de-selections.
- ///
- static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id option,
- set: 'id option -> 'model -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSelectedItem.opt subModelSeqBindingName
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsgWithModel set
- >> Binding.addCaching
-
- ///
- /// Creates a two-way binding to a SelectedItem-like property where
- /// the
- /// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF view
- /// models to/from their corresponding IDs, so the Elmish user code only has
- /// to work with the IDs.
- ///
- /// Only use this if you are unable to use some kind of SelectedValue
- /// or
- /// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when initializing
- /// the bindings if
- /// does not correspond to a binding, and it will
- /// throw at runtime if the inferred 'id type does not match the
- /// actual ID type used in that binding.
- ///
- ///
- /// The name of the binding used as the items
- /// source.
- ///
- /// Gets the selected sub-model/sub-binding ID from the
- /// model.
- ///
- /// Returns the message to dispatch on selections/de-selections.
- ///
- ///
- /// Wraps the dispatch function with additional behavior, such as
- /// throttling, debouncing, or limiting.
- ///
- []
- static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id option,
- set: 'id option -> 'model -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
- >> Binding.alterMsgStream wrapDispatch
+ ///
+ /// Creates a lazily evaluated one-way binding to an optional value. The
+ /// binding automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side. will be called only when the output of changes, as determined by .
+ ///
+ /// This may have better performance than a non-lazy binding for expensive
+ /// computations (but may be less performant for non-expensive functions due
+ /// to additional overhead).
+ ///
+ /// Gets the intermediate value from the model.
+ ///
+ /// Indicates whether two intermediate values are equal. Good candidates are
+ /// elmEq and refEq.
+ ///
+ /// Transforms the intermediate value into the final
+ /// type.
+ static member oneWayOptLazy
+ (
+ get: 'model -> 'a,
+ equals: 'a -> 'a -> bool,
+ map: 'a -> 'b option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.opt<'b, 'msg>
+ >> Binding.mapModel map
+ >> Binding.addLazy equals
+ >> Binding.mapModel get
+ >> Binding.addCaching
-// Some members are implemented as extensions to help overload resolution
-[]
-module Extensions =
+ ///
+ /// Creates a lazily evaluated one-way binding to an optional value. The
+ /// binding automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side. will be called only when the output of changes, as determined by .
+ ///
+ /// This may have better performance than a non-lazy binding for expensive
+ /// computations (but may be less performant for non-expensive functions due
+ /// to additional overhead).
+ ///
+ /// Gets the value from the model.
+ ///
+ /// Indicates whether two intermediate values are equal. Good candidates are
+ /// elmEq and refEq.
+ ///
+ /// Transforms the intermediate value into the final
+ /// type.
+ static member oneWayOptLazy
+ (
+ get: 'model -> 'a,
+ equals: 'a -> 'a -> bool,
+ map: 'a -> 'b voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.OneWay.vopt<'b, 'msg>
+ >> Binding.mapModel map
+ >> Binding.addLazy equals
+ >> Binding.mapModel get
+ >> Binding.addCaching
- type Binding with
/// Creates a one-way-to-source binding.
/// Returns the message to dispatch.
- static member oneWayToSource
- (set: 'a -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.id<'model, 'a>
- >> Binding.mapMsg set
+ static member oneWayToSource(set: 'a -> 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.id<'model, 'a>
+ >> Binding.mapMsgWithModel set
///
/// Creates a one-way-to-source binding to an optional value. The binding
@@ -2960,11 +774,9 @@ module Extensions =
/// a null value in the view.
///
/// Returns the message to dispatch.
- static member oneWayToSourceOpt
- (set: 'a option -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.opt
- >> Binding.mapMsg set
+ static member oneWayToSourceOpt(set: 'a option -> 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.opt
+ >> Binding.mapMsgWithModel set
///
/// Creates a one-way-to-source binding to an optional value. The binding
@@ -2972,24 +784,84 @@ module Extensions =
/// a null value in the view.
///
/// Returns the message to dispatch.
- static member oneWayToSourceOpt
- (set: 'a voption -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.OneWayToSource.vopt
- >> Binding.mapMsg set
+ static member oneWayToSourceOpt(set: 'a voption -> 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.vopt
+ >> Binding.mapMsgWithModel set
+
+
+ ///
+ /// Creates a one-way binding to a sequence of items, each uniquely
+ /// identified by the value returned by . The
+ /// binding will not be updated if the output of
+ /// does not change, as determined by .
+ /// The binding is backed by a persistent ObservableCollection, so
+ /// only changed items (as determined by )
+ /// will be replaced. If the items are complex and you want them updated
+ /// instead of replaced, consider using .
+ ///
+ /// Gets the intermediate value from the model.
+ ///
+ /// Indicates whether two intermediate values are equal. Good candidates are
+ /// elmEq and refEq.
+ ///
+ /// Transforms the value into the final collection.
+ ///
+ /// Indicates whether two collection items are equal. Good candidates are
+ /// elmEq, refEq, or simply (=).
+ ///
+ /// Gets a unique identifier for a collection
+ /// item.
+ static member oneWaySeqLazy
+ (
+ get: 'model -> 'a,
+ equals: 'a -> 'a -> bool,
+ map: 'a -> #seq<'b>,
+ itemEquals: 'b -> 'b -> bool,
+ getId: 'b -> 'id
+ ) : string -> Binding<'model, 'msg> =
+ Binding.OneWaySeq.create map itemEquals getId
+ >> Binding.addLazy equals
+ >> Binding.mapModel get
+
+
+ ///
+ /// Creates a one-way binding to a sequence of items, each uniquely
+ /// identified by the value returned by . The
+ /// binding will not be updated if the output of
+ /// is referentially equal. This is the same as calling
+ /// with equals = refEq and
+ /// map = id. The binding is backed by a persistent
+ /// ObservableCollection, so only changed items (as determined by
+ /// ) will be replaced. If the items are
+ /// complex and you want them updated instead of replaced, consider using
+ /// .
+ ///
+ /// Gets the collection from the model.
+ ///
+ /// Indicates whether two collection items are equal. Good candidates are
+ /// elmEq, refEq, or simply (=).
+ ///
+ /// Gets a unique identifier for a collection
+ /// item.
+ static member oneWaySeq
+ (
+ get: 'model -> #seq<'a>,
+ itemEquals: 'a -> 'a -> bool,
+ getId: 'a -> 'id
+ ) : string -> Binding<'model, 'msg> =
+ Binding.OneWaySeq.create id itemEquals getId
+ >> Binding.addLazy refEq
+ >> Binding.mapModel get
/// Creates a two-way binding.
/// Gets the value from the model.
/// Returns the message to dispatch.
- static member twoWay
- (get: 'model -> 'a,
- set: 'a -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
+ static member twoWay(get: 'model -> 'a, set: 'a -> 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
/// Creates a two-way binding.
/// Gets the value from the model.
@@ -3000,12 +872,13 @@ module Extensions =
///
[]
static member twoWay
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWay (get, set)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWay (get, set)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3016,13 +889,14 @@ module Extensions =
/// Gets the value from the model.
/// Returns the message to dispatch.
static member twoWayOpt
- (get: 'model -> 'a option,
- set: 'a option -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
///
/// Creates a two-way binding to an optional value. The binding
@@ -3037,12 +911,13 @@ module Extensions =
///
[]
static member twoWayOpt
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOpt (get, set)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOpt (get, set)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3053,13 +928,14 @@ module Extensions =
/// Gets the value from the model.
/// Returns the message to dispatch.
static member twoWayOpt
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
///
/// Creates a two-way binding to an optional value. The binding
@@ -3074,12 +950,13 @@ module Extensions =
///
[]
static member twoWayOpt
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOpt (get, set)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOpt (get, set)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3092,15 +969,16 @@ module Extensions =
/// Returns the validation messages from the updated model.
///
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation validate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation validate
///
/// Creates a two-way binding with validation using
@@ -3117,13 +995,14 @@ module Extensions =
///
[]
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3136,15 +1015,16 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.toList)
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> ValueOption.toList)
///
/// Creates a two-way binding with validation using
@@ -3161,13 +1041,14 @@ module Extensions =
///
[]
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3180,15 +1061,16 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> Option.toList)
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> Option.toList)
///
/// Creates a two-way binding with validation using
@@ -3205,13 +1087,14 @@ module Extensions =
///
[]
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3224,15 +1107,20 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.id<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
///
/// Creates a two-way binding with validation using
@@ -3249,20 +1137,21 @@ module Extensions =
///
[]
static member twoWayValidate
- (get: 'model -> 'a,
- set: 'a -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3270,21 +1159,22 @@ module Extensions =
/// Returns the validation messages from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation validate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation validate
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3297,20 +1187,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3318,21 +1209,22 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.toList)
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> ValueOption.toList)
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3345,20 +1237,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3366,21 +1259,22 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> Option.toList)
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> Option.toList)
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3393,20 +1287,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3414,21 +1309,26 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.vopt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3441,20 +1341,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a voption,
- set: 'a voption -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3462,21 +1363,22 @@ module Extensions =
/// Returns the validation messages from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string list)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation validate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation validate
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3489,20 +1391,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string list,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3510,21 +1413,22 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string voption)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.toList)
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> ValueOption.toList)
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3537,20 +1441,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3558,21 +1463,22 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string option)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> Option.toList)
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (validate >> Option.toList)
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3585,20 +1491,21 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> string option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3606,21 +1513,26 @@ module Extensions =
/// Returns the validation message from the updated model.
///
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> Result<'ignored, string>)
- : string -> Binding<'model, 'msg> =
- Binding.TwoWay.opt<'a>
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addValidation (validate >> ValueOption.ofError >> ValueOption.toList)
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
///
/// Creates a two-way binding to an optional value with validation using
- /// INotifyDataErrorInfo. The binding automatically converts
- /// between the optional source value and an unwrapped (possibly
- /// null) value on the view side.
+ /// INotifyDataErrorInfo. The binding automatically converts between
+ /// the optional source value and an unwrapped (possibly null) value
+ /// on the view side.
///
/// Gets the value from the model.
/// Returns the message to dispatch.
@@ -3633,30 +1545,27 @@ module Extensions =
///
[]
static member twoWayOptValidate
- (get: 'model -> 'a option,
- set: 'a option -> 'msg,
- validate: 'model -> Result<'ignored, string>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.twoWayOptValidate (get, set, validate)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'model -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a Command binding that dispatches the specified message
- /// and can always execute.
+ /// Creates a Command binding that depends only on the model (not the
+ /// CommandParameter) and can always execute.
///
/// Returns the message to dispatch.
- static member cmd
- (exec: 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (fun _ -> exec |> ValueSome)
- (fun _ -> true)
+ static member cmd(exec: 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (exec >> ValueSome) (fun _ -> true)
///
- /// Creates a Command binding that dispatches the specified message
- /// and can always execute.
+ /// Creates a Command binding that depends only on the model (not the
+ /// CommandParameter) and can always execute.
///
/// Returns the message to dispatch.
///
@@ -3665,30 +1574,30 @@ module Extensions =
///
[]
static member cmd
- (exec: 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmd exec
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmd exec
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a Command binding that dispatches the specified message
- /// and can execute if returns true.
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns true.
///
/// Returns the message to dispatch.
/// Indicates whether the command can execute.
- static member cmdIf
- (exec: 'msg,
- canExec: 'model -> bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.create
- (fun _ -> exec |> ValueSome)
- canExec
+ static member cmdIf(exec: 'model -> 'msg, canExec: 'model -> bool) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (exec >> ValueSome) canExec
///
- /// Creates a Command binding that dispatches the specified message
- /// and can execute if returns true.
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns true.
///
/// Returns the message to dispatch.
/// Indicates whether the command can execute.
@@ -3698,12 +1607,112 @@ module Extensions =
///
[]
static member cmdIf
- (exec: 'msg,
- canExec: 'model -> bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdIf (exec, canExec)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: 'model -> 'msg,
+ canExec: 'model -> bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdIf (exec, canExec)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns ValueSome.
+ ///
+ /// Returns the message to dispatch.
+ static member cmdIf(exec: 'model -> 'msg voption) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create exec (exec >> ValueOption.isSome)
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns ValueSome.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdIf
+ (
+ exec: 'model -> 'msg voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdIf exec
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns Some.
+ ///
+ /// Returns the message to dispatch.
+ static member cmdIf(exec: 'model -> 'msg option) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (exec >> ValueOption.ofOption) (exec >> Option.isSome)
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns Some.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdIf
+ (
+ exec: 'model -> 'msg option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdIf exec
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation functions
+ /// for inputs and commands.
+ ///
+ /// Returns the message to dispatch.
+ static member cmdIf(exec: 'model -> Result<'msg, 'ignored>) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (exec >> ValueOption.ofOk) (exec >> Result.isOk)
+
+ ///
+ /// Creates a conditional Command binding that depends only on the
+ /// model (not the CommandParameter) and can execute if
+ /// returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation functions
+ /// for inputs and commands.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdIf
+ (
+ exec: 'model -> Result<'msg, 'ignored>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdIf exec
+ >> Binding.alterMsgStream wrapDispatch
///
@@ -3712,13 +1721,8 @@ module Extensions =
/// and can always execute.
///
/// Returns the message to dispatch.
- static member cmdParam
- (exec: obj -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p _ -> exec p |> ValueSome)
- (fun _ _ -> true)
- false
+ static member cmdParam(exec: obj -> 'model -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam (fun p model -> exec p model |> ValueSome) (fun _ _ -> true) false
///
/// Creates a Command binding that depends on the
@@ -3732,19 +1736,21 @@ module Extensions =
///
[]
static member cmdParam
- (exec: obj -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParam exec
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParam exec
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a conditional Command binding that depends on the
+ /// Creates a Command binding that depends on the
/// CommandParameter
- /// and can execute if returns ValueSome.
+ /// and can execute if returns true.
///
/// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
///
/// If true, CanExecuteChanged will trigger every time WPF's
/// CommandManager
@@ -3754,38 +1760,41 @@ module Extensions =
/// to another UI property.
///
static member cmdParamIf
- (exec: obj -> 'msg voption,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p _ -> exec p)
- (fun p _ -> exec p |> ValueOption.isSome)
- (defaultArg uiBoundCmdParam false)
+ (
+ exec: obj -> 'model -> 'msg,
+ canExec: obj -> 'model -> bool,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam (fun p m -> exec p m |> ValueSome) canExec (defaultArg uiBoundCmdParam false)
///
- /// Creates a conditional Command binding that depends on the
+ /// Creates a Command binding that depends on the
/// CommandParameter
- /// and can execute if returns ValueSome.
+ /// and can execute if returns true.
///
/// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
///
/// Wraps the dispatch function with additional behavior, such as
/// throttling, debouncing, or limiting.
///
[]
static member cmdParamIf
- (exec: obj -> 'msg voption,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg,
+ canExec: obj -> 'model -> bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, canExec)
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a conditional Command binding that depends on the
+ /// Creates a Command binding that depends on the
/// CommandParameter
- /// and can execute if returns ValueSome.
+ /// and can execute if returns true.
///
/// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
///
/// If true, CanExecuteChanged will trigger every time WPF's
/// CommandManager
@@ -3800,18 +1809,20 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> 'msg voption,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg,
+ canExec: obj -> 'model -> bool,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, canExec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Some.
+ /// and can execute if returns ValueSome.
///
/// Returns the message to dispatch.
///
@@ -3823,18 +1834,16 @@ module Extensions =
/// to another UI property.
///
static member cmdParamIf
- (exec: obj -> 'msg option,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p _ -> exec p |> ValueOption.ofOption)
- (fun p _ -> exec p |> Option.isSome)
- (defaultArg uiBoundCmdParam false)
+ (
+ exec: obj -> 'model -> 'msg voption,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam exec (fun p m -> exec p m |> ValueOption.isSome) (defaultArg uiBoundCmdParam false)
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Some.
+ /// and can execute if returns ValueSome.
///
/// Returns the message to dispatch.
///
@@ -3843,16 +1852,17 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> 'msg option,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Some.
+ /// and can execute if returns ValueSome.
///
/// Returns the message to dispatch.
///
@@ -3869,21 +1879,19 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> 'msg option,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg voption,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation
- /// functions for inputs and commands.
+ /// and can execute if returns Some.
///
/// Returns the message to dispatch.
///
@@ -3895,21 +1903,19 @@ module Extensions =
/// to another UI property.
///
static member cmdParamIf
- (exec: obj -> Result<'msg, 'ignored>,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p _ -> exec p |> ValueOption.ofOk)
- (fun p _ -> exec p |> Result.isOk)
- (defaultArg uiBoundCmdParam false)
+ (
+ exec: obj -> 'model -> 'msg option,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p m -> exec p m |> ValueOption.ofOption)
+ (fun p m -> exec p m |> Option.isSome)
+ (defaultArg uiBoundCmdParam false)
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation
- /// functions for inputs and commands.
+ /// and can execute if returns Some.
///
/// Returns the message to dispatch.
///
@@ -3918,19 +1924,17 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> Result<'msg, 'ignored>,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf exec
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns Ok.
- ///
- /// This overload allows more easily re-using the same validation
- /// functions for inputs and commands.
+ /// and can execute if returns Some.
///
/// Returns the message to dispatch.
///
@@ -3947,21 +1951,24 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> Result<'msg, 'ignored>,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> 'msg option,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a Command binding that depends on the
+ /// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns true.
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation functions
+ /// for inputs and commands.
///
/// Returns the message to dispatch.
- /// Indicates whether the command can execute.
///
/// If true, CanExecuteChanged will trigger every time WPF's
/// CommandManager
@@ -3971,42 +1978,46 @@ module Extensions =
/// to another UI property.
///
static member cmdParamIf
- (exec: obj -> 'msg,
- canExec: obj -> bool,
- ?uiBoundCmdParam: bool)
- : string -> Binding<'model, 'msg> =
- Binding.Cmd.createWithParam
- (fun p _ -> exec p |> ValueSome)
- (fun p _ -> canExec p)
- (defaultArg uiBoundCmdParam false)
+ (
+ exec: obj -> 'model -> Result<'msg, 'ignored>,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p m -> exec p m |> ValueOption.ofOk)
+ (fun p m -> exec p m |> Result.isOk)
+ (defaultArg uiBoundCmdParam false)
///
- /// Creates a Command binding that depends on the
+ /// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns true.
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation functions
+ /// for inputs and commands.
///
/// Returns the message to dispatch.
- /// Indicates whether the command can execute.
///
/// Wraps the dispatch function with additional behavior, such as
/// throttling, debouncing, or limiting.
///
[]
static member cmdParamIf
- (exec: obj -> 'msg,
- canExec: obj -> bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, canExec)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> Result<'msg, 'ignored>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
///
- /// Creates a Command binding that depends on the
+ /// Creates a conditional Command binding that depends on the
/// CommandParameter
- /// and can execute if returns true.
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation functions
+ /// for inputs and commands.
///
/// Returns the message to dispatch.
- /// Indicates whether the command can execute.
///
/// If true, CanExecuteChanged will trigger every time WPF's
/// CommandManager
@@ -4021,32 +2032,793 @@ module Extensions =
///
[]
static member cmdParamIf
- (exec: obj -> 'msg,
- canExec: obj -> bool,
- uiBoundCmdParam: bool,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.cmdParamIf (exec, canExec, uiBoundCmdParam)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ exec: obj -> 'model -> Result<'msg, 'ignored>,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ []
+ static member subModel
+ (
+ getSubModel: 'model -> 'subModel,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ toMsg: 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.required bindings
+ >> Binding.mapModel (fun m -> toBindingModel (m, getSubModel m))
+ >> Binding.mapMsg toMsg
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ []
+ static member subModel
+ (
+ getSubModel: 'model -> 'subModel,
+ toMsg: 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.required bindings
+ >> Binding.mapModel (fun m -> (m, getSubModel m))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings.
+ /// You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// Gets the sub-model from the model.
+ /// Returns the bindings for the sub-model.
+ [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with its implementation.")>]
+ static member subModel
+ (
+ getSubModel: 'model -> 'subModel,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.required bindings
+ >> Binding.mapModel (fun m -> (m, getSubModel m))
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type, and may not exist. If it does not exist, bindings to this
+ /// model will return null unless is
+ /// true, in which case the last non-null model will be
+ /// returned. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ []
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel voption,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ toMsg: 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.vopt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m ->
+ getSubModel m
+ |> ValueOption.map (fun sub -> toBindingModel (m, sub)))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type, and may not exist. If it does not exist, bindings to this
+ /// model will return null unless is
+ /// true, in which case the last non-null model will be
+ /// returned. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ []
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel option,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ toMsg: 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.opt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m ->
+ getSubModel m
+ |> Option.map (fun sub -> toBindingModel (m, sub)))
+ >> Binding.mapMsg toMsg
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type, and may not exist. If it does not exist, bindings to this
+ /// model will return null unless is
+ /// true, in which case the last non-null model will be
+ /// returned. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ []
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel voption,
+ toMsg: 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.vopt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m ->
+ getSubModel m
+ |> ValueOption.map (fun sub -> (m, sub)))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings and
+ /// message type, and may not exist. If it does not exist, bindings to this
+ /// model will return null unless is
+ /// true, in which case the last non-null model will be
+ /// returned. You typically bind this to the DataContext of a
+ /// UserControl or similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ []
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel option,
+ toMsg: 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.opt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m -> getSubModel m |> Option.map (fun sub -> (m, sub)))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings,
+ /// and may not exist. If it does not exist, bindings to this model will
+ /// return null unless is true, in
+ /// which case the last non-null model will be returned. You
+ /// typically bind this to the DataContext of a UserControl or
+ /// similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with (a specialization of) its implementation.")>]
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel voption,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.vopt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m ->
+ getSubModel m
+ |> ValueOption.map (fun sub -> (m, sub)))
+
+
+ ///
+ /// Creates a binding to a sub-model/component that has its own bindings,
+ /// and may not exist. If it does not exist, bindings to this model will
+ /// return null unless is true, in
+ /// which case the last non-null model will be returned. You
+ /// typically bind this to the DataContext of a UserControl or
+ /// similar.
+ ///
+ /// The 'sticky' part is useful if you want to e.g. animate away a
+ /// UserControl when the model is missing, but don't want the data
+ /// used by that control to be cleared once the animation starts. (The
+ /// animation must be triggered using another binding since this will never
+ /// return null.)
+ ///
+ /// Gets the sub-model from the model.
+ /// Returns the bindings for the sub-model.
+ ///
+ /// If true, when the model is missing, the last non-null
+ /// model will be returned instead of null.
+ ///
+ [ Binding<'model, 'msg> list\". To avoid a compile error when upgrading, replace this method call with (a specialization of) its implementation.")>]
+ static member subModelOpt
+ (
+ getSubModel: 'model -> 'subModel option,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list,
+ ?sticky: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModel.opt bindings
+ >> if (defaultArg sticky false) then
+ Binding.addLazy (fun previous next -> previous.IsSome && next.IsNone)
+ else
+ id
+ >> Binding.mapModel (fun m -> getSubModel m |> Option.map (fun sub -> (m, sub)))
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// If you don't need a sub-model, you can use
+ /// WindowState<unit> to just control the Window visibility,
+ /// and pass fst to .
+ ///
+ /// Gets the window state and a sub-model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ toMsg: 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
+ getWindow: 'model -> Dispatch<'msg> -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelWin.create
+ (fun m ->
+ getState m
+ |> WindowState.map (fun sub -> toBindingModel (m, sub)))
+ (fun args -> DynamicViewModel<'bindingModel, 'bindingMsg>(args, bindings ()))
+ IViewModel.updateModel
+ (fun _ -> toMsg)
+ (fun m d -> upcast getWindow m d)
+ (defaultArg isModal false)
+ (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// If you don't need a sub-model, you can use
+ /// WindowState<unit> to just control the Window visibility,
+ /// and pass fst to .
+ ///
+ /// Gets the window state and a sub-model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ toMsg: 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list,
+ getWindow: unit -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelWin (
+ getState,
+ toBindingModel,
+ toMsg,
+ bindings,
+ (fun _ _ -> getWindow ()),
+ ?onCloseRequested = onCloseRequested,
+ ?isModal = isModal
+ )
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// Gets the window state and a sub-model.
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ toMsg: 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
+ getWindow: 'model -> Dispatch<'msg> -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelWin.create
+ (fun m ->
+ getState m
+ |> WindowState.map (fun sub -> (m, sub)))
+ (fun args -> DynamicViewModel<'model * 'subModel, 'subMsg>(args, bindings ()))
+ IViewModel.updateModel
+ (fun _ -> toMsg)
+ (fun m d -> upcast getWindow m d)
+ (defaultArg isModal false)
+ (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// Gets the window state and a sub-model.
+ ///
+ /// Converts the messages used in the bindings to parent model messages
+ /// (e.g. a parent message union case that wraps the child message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ toMsg: 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list,
+ getWindow: unit -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelWin (
+ getState,
+ toMsg,
+ bindings,
+ (fun _ _ -> getWindow ()),
+ ?onCloseRequested = onCloseRequested,
+ ?isModal = isModal
+ )
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// Gets the window state and a sub-model.
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list,
+ getWindow: 'model -> Dispatch<'msg> -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelWin.create
+ (fun m ->
+ getState m
+ |> WindowState.map (fun sub -> (m, sub)))
+ (fun args -> DynamicViewModel<'model * 'subModel, 'msg>(args, bindings ()))
+ IViewModel.updateModel
+ (fun _ -> id)
+ (fun m d -> upcast getWindow m d)
+ (defaultArg isModal false)
+ (fun _ -> defaultArg (onCloseRequested |> Option.map ValueSome) ValueNone)
+
+
+ ///
+ /// Like , but uses the WindowState wrapper
+ /// to show/hide/close a new window that will have the specified bindings as
+ /// its DataContext.
+ ///
+ /// You do not need to set the DataContext yourself (neither in code
+ /// nor XAML).
+ ///
+ /// The window can only be closed/hidden by changing the return value of
+ /// , and can not be directly closed by the
+ /// user. External close attempts (the Close/X button, Alt+F4, or System
+ /// Menu -> Close) will cause the message specified by
+ /// to be dispatched. You should supply
+ /// and react to this in a manner that
+ /// will not confuse a user trying to close the window (e.g. by closing it,
+ /// or displaying relevant feedback to the user.)
+ ///
+ /// Gets the window state and a sub-model.
+ /// Returns the bindings for the sub-model.
+ ///
+ /// The function used to get and configure the window.
+ ///
+ ///
+ /// The message to be dispatched on external close attempts (the Close/X
+ /// button, Alt+F4, or System Menu -> Close).
+ ///
+ ///
+ /// Specifies whether the window will be shown modally (using
+ /// window.ShowDialog, blocking the rest of the app) or non-modally (using
+ /// window.Show).
+ ///
+ static member subModelWin
+ (
+ getState: 'model -> WindowState<'subModel>,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list,
+ getWindow: unit -> #Window,
+ ?onCloseRequested: 'msg,
+ ?isModal: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelWin (
+ getState,
+ bindings,
+ (fun _ _ -> getWindow ()),
+ ?onCloseRequested = onCloseRequested,
+ ?isModal = isModal
+ )
+
+ static member subModelSeq
+ (getBindings: unit -> Binding<'model, 'msg> list)
+ : string -> Binding<'model seq, int * 'msg> =
+ Binding.SubModelSeqUnkeyed.create
+ (fun args -> DynamicViewModel<'model, 'msg>(args, getBindings ()))
+ IViewModel.updateModel
+
+ static member subModelSeq
+ (
+ getBindings: unit -> Binding<'model, 'msg> list,
+ getId: 'model -> 'id
+ ) : string -> Binding<'model seq, 'id * 'msg> =
+ Binding.SubModelSeqKeyed.create
+ (fun args -> DynamicViewModel<'model, 'msg>(args, getBindings ()))
+ IViewModel.updateModel
+ getId
+ (IViewModel.currentModel >> getId)
+
+
+ ///
+ /// Creates a binding to a sequence of sub-models, each uniquely identified
+ /// by the value returned by . The sub-models have
+ /// their own bindings and message type. You typically bind this to the
+ /// ItemsSource of an ItemsControl, ListView,
+ /// TreeView, etc.
+ ///
+ /// Gets the sub-models from the model.
+ ///
+ /// Converts the models to the model used by the bindings.
+ ///
+ /// Gets a unique identifier for a sub-model.
+ ///
+ /// Converts the sub-model ID and messages used in the bindings to parent
+ /// model messages (e.g. a parent message union case that wraps the
+ /// sub-model ID and message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ static member subModelSeq
+ (
+ getSubModels: 'model -> #seq<'subModel>,
+ toBindingModel: 'model * 'subModel -> 'bindingModel,
+ getId: 'bindingModel -> 'id,
+ toMsg: 'id * 'bindingMsg -> 'msg,
+ bindings: unit -> Binding<'bindingModel, 'bindingMsg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSeqKeyed.create
+ (fun args -> DynamicViewModel<'bindingModel, 'bindingMsg>(args, bindings ()))
+ IViewModel.updateModel
+ getId
+ (IViewModel.currentModel >> getId)
+ >> Binding.mapModel (fun m ->
+ getSubModels m
+ |> Seq.map (fun sub -> toBindingModel (m, sub)))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sequence of sub-models, each uniquely identified
+ /// by the value returned by . The sub-models have
+ /// their own bindings and message type. You typically bind this to the
+ /// ItemsSource of an ItemsControl, ListView,
+ /// TreeView, etc.
+ ///
+ /// Gets the sub-models from the model.
+ /// Gets a unique identifier for a sub-model.
+ ///
+ /// Converts the sub-model ID and messages used in the bindings to parent
+ /// model messages (e.g. a parent message union case that wraps the
+ /// sub-model ID and message type).
+ ///
+ /// Returns the bindings for the sub-model.
+ static member subModelSeq
+ (
+ getSubModels: 'model -> #seq<'subModel>,
+ getId: 'subModel -> 'id,
+ toMsg: 'id * 'subMsg -> 'msg,
+ bindings: unit -> Binding<'model * 'subModel, 'subMsg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSeqKeyed.create
+ (fun args -> DynamicViewModel<'model * 'subModel, 'subMsg>(args, bindings ()))
+ IViewModel.updateModel
+ (snd >> getId)
+ (IViewModel.currentModel >> snd >> getId)
+ >> Binding.mapModel (fun m -> getSubModels m |> Seq.map (fun sub -> (m, sub)))
+ >> Binding.mapMsg toMsg
+
+
+ ///
+ /// Creates a binding to a sequence of sub-models, each uniquely identified
+ /// by the value returned by . The sub-models have
+ /// their own bindings. You typically bind this to the ItemsSource of
+ /// an
+ /// ItemsControl, ListView, TreeView, etc.
+ ///
+ /// Gets the sub-models from the model.
+ /// Gets a unique identifier for a sub-model.
+ /// Returns the bindings for the sub-model.
+ static member subModelSeq
+ (
+ getSubModels: 'model -> #seq<'subModel>,
+ getId: 'subModel -> 'id,
+ bindings: unit -> Binding<'model * 'subModel, 'msg> list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSeqKeyed.create
+ (fun args -> DynamicViewModel<'model * 'subModel, 'msg>(args, bindings ()))
+ IViewModel.updateModel
+ (snd >> getId)
+ (IViewModel.currentModel >> snd >> getId)
+ >> Binding.mapModel (fun m -> getSubModels m |> Seq.map (fun sub -> (m, sub)))
+ >> Binding.mapMsg snd
///
/// Creates a two-way binding to a SelectedItem-like property where
/// the
/// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF
- /// view models to/from their corresponding IDs, so the Elmish user code
- /// only has to work with the IDs.
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
///
- /// Only use this if you are unable to use some kind of
- /// SelectedValue or
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or
/// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when
- /// initializing the bindings if
- /// does not correspond to a binding, and it
- /// will throw at runtime if the inferred 'id type does not
- /// match the actual ID type used in that binding.
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
///
///
/// The name of the binding used as the items
@@ -4058,33 +2830,33 @@ module Extensions =
/// Returns the message to dispatch on selections/de-selections.
///
static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id voption,
- set: 'id voption -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSelectedItem.vopt subModelSeqBindingName
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addCaching
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id voption,
+ set: 'id voption -> 'model -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSelectedItem.vopt subModelSeqBindingName
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addCaching
///
/// Creates a two-way binding to a SelectedItem-like property where
/// the
/// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF
- /// view models to/from their corresponding IDs, so the Elmish user code
- /// only has to work with the IDs.
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
///
- /// Only use this if you are unable to use some kind of
- /// SelectedValue or
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or
/// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when
- /// initializing the bindings if
- /// does not correspond to a binding, and it
- /// will throw at runtime if the inferred 'id type does not
- /// match the actual ID type used in that binding.
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
///
///
/// The name of the binding used as the items
@@ -4101,32 +2873,32 @@ module Extensions =
///
[]
static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id voption,
- set: 'id voption -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id voption,
+ set: 'id voption -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
+ >> Binding.alterMsgStream wrapDispatch
///
/// Creates a two-way binding to a SelectedItem-like property where
/// the
/// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF
- /// view models to/from their corresponding IDs, so the Elmish user code
- /// only has to work with the IDs.
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
///
- /// Only use this if you are unable to use some kind of
- /// SelectedValue or
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or
/// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when
- /// initializing the bindings if
- /// does not correspond to a binding, and it
- /// will throw at runtime if the inferred 'id type does not
- /// match the actual ID type used in that binding.
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
///
///
/// The name of the binding used as the items
@@ -4138,33 +2910,33 @@ module Extensions =
/// Returns the message to dispatch on selections/de-selections.
///
static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id option,
- set: 'id option -> 'msg)
- : string -> Binding<'model, 'msg> =
- Binding.SubModelSelectedItem.opt subModelSeqBindingName
- >> Binding.addLazy (=)
- >> Binding.mapModel get
- >> Binding.mapMsg set
- >> Binding.addCaching
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id option,
+ set: 'id option -> 'model -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSelectedItem.opt subModelSeqBindingName
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsgWithModel set
+ >> Binding.addCaching
///
/// Creates a two-way binding to a SelectedItem-like property where
/// the
/// ItemsSource-like property is a
- /// binding. Automatically converts the dynamically created Elmish.WPF
- /// view models to/from their corresponding IDs, so the Elmish user code
- /// only has to work with the IDs.
+ /// binding. Automatically converts the dynamically created Elmish.WPF view
+ /// models to/from their corresponding IDs, so the Elmish user code only has
+ /// to work with the IDs.
///
- /// Only use this if you are unable to use some kind of
- /// SelectedValue or
+ /// Only use this if you are unable to use some kind of SelectedValue
+ /// or
/// SelectedIndex property with a normal
- /// binding. This binding is less type-safe. It will throw when
- /// initializing the bindings if
- /// does not correspond to a binding, and it
- /// will throw at runtime if the inferred 'id type does not
- /// match the actual ID type used in that binding.
+ /// binding. This binding is less type-safe. It will throw when initializing
+ /// the bindings if
+ /// does not correspond to a binding, and it will
+ /// throw at runtime if the inferred 'id type does not match the
+ /// actual ID type used in that binding.
///
///
/// The name of the binding used as the items
@@ -4181,10 +2953,1281 @@ module Extensions =
///
[]
static member subModelSelectedItem
- (subModelSeqBindingName: string,
- get: 'model -> 'id option,
- set: 'id option -> 'msg,
- wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>)
- : string -> Binding<'model, 'msg> =
- Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
- >> Binding.alterMsgStream wrapDispatch
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id option,
+ set: 'id option -> 'model -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+
+// Some members are implemented as extensions to help overload resolution
+[]
+module Extensions =
+
+ type Binding with
+
+ /// Creates a one-way-to-source binding.
+ /// Returns the message to dispatch.
+ static member oneWayToSource(set: 'a -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.id<'model, 'a>
+ >> Binding.mapMsg set
+
+ ///
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ ///
+ /// Returns the message to dispatch.
+ static member oneWayToSourceOpt(set: 'a option -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.opt >> Binding.mapMsg set
+
+ ///
+ /// Creates a one-way-to-source binding to an optional value. The binding
+ /// automatically converts between a missing value in the model and
+ /// a null value in the view.
+ ///
+ /// Returns the message to dispatch.
+ static member oneWayToSourceOpt(set: 'a voption -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.OneWayToSource.vopt >> Binding.mapMsg set
+
+
+ /// Creates a two-way binding.
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ static member twoWay(get: 'model -> 'a, set: 'a -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+
+ /// Creates a two-way binding.
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWay
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWay (get, set)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ static member twoWayOpt(get: 'model -> 'a option, set: 'a option -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+
+ ///
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOpt
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOpt (get, set)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ static member twoWayOpt(get: 'model -> 'a voption, set: 'a voption -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+
+ ///
+ /// Creates a two-way binding to an optional value. The binding
+ /// automatically converts between the optional source value and an
+ /// unwrapped (possibly null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOpt
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOpt (get, set)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation validate
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> ValueOption.toList)
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> Option.toList)
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.id<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
+
+ ///
+ /// Creates a two-way binding with validation using
+ /// INotifyDataErrorInfo.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayValidate
+ (
+ get: 'model -> 'a,
+ set: 'a -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation validate
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> ValueOption.toList)
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> Option.toList)
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.vopt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a voption,
+ set: 'a voption -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string list
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation validate
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation messages from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string list,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string voption
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> ValueOption.toList)
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string option
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (validate >> Option.toList)
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> string option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> Result<'ignored, string>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.TwoWay.opt<'a>
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addValidation (
+ validate
+ >> ValueOption.ofError
+ >> ValueOption.toList
+ )
+
+ ///
+ /// Creates a two-way binding to an optional value with validation using
+ /// INotifyDataErrorInfo. The binding automatically converts
+ /// between the optional source value and an unwrapped (possibly
+ /// null) value on the view side.
+ ///
+ /// Gets the value from the model.
+ /// Returns the message to dispatch.
+ ///
+ /// Returns the validation message from the updated model.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member twoWayOptValidate
+ (
+ get: 'model -> 'a option,
+ set: 'a option -> 'msg,
+ validate: 'model -> Result<'ignored, string>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.twoWayOptValidate (get, set, validate)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a Command binding that dispatches the specified message
+ /// and can always execute.
+ ///
+ /// Returns the message to dispatch.
+ static member cmd(exec: 'msg) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (fun _ -> exec |> ValueSome) (fun _ -> true)
+
+ ///
+ /// Creates a Command binding that dispatches the specified message
+ /// and can always execute.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmd
+ (
+ exec: 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmd exec
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a Command binding that dispatches the specified message
+ /// and can execute if returns true.
+ ///
+ /// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
+ static member cmdIf(exec: 'msg, canExec: 'model -> bool) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.create (fun _ -> exec |> ValueSome) canExec
+
+ ///
+ /// Creates a Command binding that dispatches the specified message
+ /// and can execute if returns true.
+ ///
+ /// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdIf
+ (
+ exec: 'msg,
+ canExec: 'model -> bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdIf (exec, canExec)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a Command binding that depends on the
+ /// CommandParameter
+ /// and can always execute.
+ ///
+ /// Returns the message to dispatch.
+ static member cmdParam(exec: obj -> 'msg) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam (fun p _ -> exec p |> ValueSome) (fun _ _ -> true) false
+
+ ///
+ /// Creates a Command binding that depends on the
+ /// CommandParameter
+ /// and can always execute.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParam
+ (
+ exec: obj -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParam exec
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns ValueSome.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ static member cmdParamIf(exec: obj -> 'msg voption, ?uiBoundCmdParam: bool) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p _ -> exec p)
+ (fun p _ -> exec p |> ValueOption.isSome)
+ (defaultArg uiBoundCmdParam false)
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns ValueSome.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg voption,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns ValueSome.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg voption,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Some.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ static member cmdParamIf(exec: obj -> 'msg option, ?uiBoundCmdParam: bool) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p _ -> exec p |> ValueOption.ofOption)
+ (fun p _ -> exec p |> Option.isSome)
+ (defaultArg uiBoundCmdParam false)
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Some.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg option,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Some.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg option,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation
+ /// functions for inputs and commands.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ static member cmdParamIf
+ (
+ exec: obj -> Result<'msg, 'ignored>,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p _ -> exec p |> ValueOption.ofOk)
+ (fun p _ -> exec p |> Result.isOk)
+ (defaultArg uiBoundCmdParam false)
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation
+ /// functions for inputs and commands.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> Result<'msg, 'ignored>,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf exec
+ >> Binding.alterMsgStream wrapDispatch
+
+ ///
+ /// Creates a conditional Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns Ok.
+ ///
+ /// This overload allows more easily re-using the same validation
+ /// functions for inputs and commands.
+ ///
+ /// Returns the message to dispatch.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> Result<'msg, 'ignored>,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns true.
+ ///
+ /// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg,
+ canExec: obj -> bool,
+ ?uiBoundCmdParam: bool
+ ) : string -> Binding<'model, 'msg> =
+ Binding.Cmd.createWithParam
+ (fun p _ -> exec p |> ValueSome)
+ (fun p _ -> canExec p)
+ (defaultArg uiBoundCmdParam false)
+
+ ///
+ /// Creates a Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns true.
+ ///
+ /// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg,
+ canExec: obj -> bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, canExec)
+ >> Binding.alterMsgStream wrapDispatch
+
+ ///
+ /// Creates a Command binding that depends on the
+ /// CommandParameter
+ /// and can execute if returns true.
+ ///
+ /// Returns the message to dispatch.
+ /// Indicates whether the command can execute.
+ ///
+ /// If true, CanExecuteChanged will trigger every time WPF's
+ /// CommandManager
+ /// detects UI changes that could potentially influence the command's
+ /// ability to execute. This will likely lead to many more triggers than
+ /// necessary, but is needed if you have bound the CommandParameter
+ /// to another UI property.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member cmdParamIf
+ (
+ exec: obj -> 'msg,
+ canExec: obj -> bool,
+ uiBoundCmdParam: bool,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.cmdParamIf (exec, canExec, uiBoundCmdParam)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the
+ /// ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF
+ /// view models to/from their corresponding IDs, so the Elmish user code
+ /// only has to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of
+ /// SelectedValue or
+ /// SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when
+ /// initializing the bindings if
+ /// does not correspond to a binding, and it
+ /// will throw at runtime if the inferred 'id type does not
+ /// match the actual ID type used in that binding.
+ ///
+ ///
+ /// The name of the binding used as the items
+ /// source.
+ ///
+ /// Gets the selected sub-model/sub-binding ID from the
+ /// model.
+ ///
+ /// Returns the message to dispatch on selections/de-selections.
+ ///
+ static member subModelSelectedItem
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id voption,
+ set: 'id voption -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSelectedItem.vopt subModelSeqBindingName
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addCaching
+
+ ///
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the
+ /// ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF
+ /// view models to/from their corresponding IDs, so the Elmish user code
+ /// only has to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of
+ /// SelectedValue or
+ /// SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when
+ /// initializing the bindings if
+ /// does not correspond to a binding, and it
+ /// will throw at runtime if the inferred 'id type does not
+ /// match the actual ID type used in that binding.
+ ///
+ ///
+ /// The name of the binding used as the items
+ /// source.
+ ///
+ /// Gets the selected sub-model/sub-binding ID from the
+ /// model.
+ ///
+ /// Returns the message to dispatch on selections/de-selections.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member subModelSelectedItem
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id voption,
+ set: 'id voption -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
+ >> Binding.alterMsgStream wrapDispatch
+
+
+ ///
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the
+ /// ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF
+ /// view models to/from their corresponding IDs, so the Elmish user code
+ /// only has to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of
+ /// SelectedValue or
+ /// SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when
+ /// initializing the bindings if
+ /// does not correspond to a binding, and it
+ /// will throw at runtime if the inferred 'id type does not
+ /// match the actual ID type used in that binding.
+ ///
+ ///
+ /// The name of the binding used as the items
+ /// source.
+ ///
+ /// Gets the selected sub-model/sub-binding ID from the
+ /// model.
+ ///
+ /// Returns the message to dispatch on selections/de-selections.
+ ///
+ static member subModelSelectedItem
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id option,
+ set: 'id option -> 'msg
+ ) : string -> Binding<'model, 'msg> =
+ Binding.SubModelSelectedItem.opt subModelSeqBindingName
+ >> Binding.addLazy (=)
+ >> Binding.mapModel get
+ >> Binding.mapMsg set
+ >> Binding.addCaching
+
+ ///
+ /// Creates a two-way binding to a SelectedItem-like property where
+ /// the
+ /// ItemsSource-like property is a
+ /// binding. Automatically converts the dynamically created Elmish.WPF
+ /// view models to/from their corresponding IDs, so the Elmish user code
+ /// only has to work with the IDs.
+ ///
+ /// Only use this if you are unable to use some kind of
+ /// SelectedValue or
+ /// SelectedIndex property with a normal
+ /// binding. This binding is less type-safe. It will throw when
+ /// initializing the bindings if
+ /// does not correspond to a binding, and it
+ /// will throw at runtime if the inferred 'id type does not
+ /// match the actual ID type used in that binding.
+ ///
+ ///
+ /// The name of the binding used as the items
+ /// source.
+ ///
+ /// Gets the selected sub-model/sub-binding ID from the
+ /// model.
+ ///
+ /// Returns the message to dispatch on selections/de-selections.
+ ///
+ ///
+ /// Wraps the dispatch function with additional behavior, such as
+ /// throttling, debouncing, or limiting.
+ ///
+ []
+ static member subModelSelectedItem
+ (
+ subModelSeqBindingName: string,
+ get: 'model -> 'id option,
+ set: 'id option -> 'msg,
+ wrapDispatch: Dispatch<'msg> -> Dispatch<'msg>
+ ) : string -> Binding<'model, 'msg> =
+ Binding.subModelSelectedItem (subModelSeqBindingName, get, set)
+ >> Binding.alterMsgStream wrapDispatch
diff --git a/src/Samples/Samples.generated.sln b/src/Samples/Samples.generated.sln
new file mode 100644
index 00000000..a8dded5b
--- /dev/null
+++ b/src/Samples/Samples.generated.sln
@@ -0,0 +1,121 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.002.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capabilities", "Capabilities\Capabilities.csproj", "{11D2A55F-9315-4538-B3E4-44868816E81C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBindingsAndBehaviors", "EventBindingsAndBehaviors\EventBindingsAndBehaviors.csproj", "{26B784E2-4A97-49CB-9DD2-AD23F85A999D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileDialogs", "FileDialogs\FileDialogs.csproj", "{49005859-27DB-4A96-B80F-2C15AFF1A828}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileDialogsCmdMsg", "FileDialogsCmdMsg\FileDialogsCmdMsg.csproj", "{1E366BD6-1750-4150-A6AC-2615551E0E51}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Multiselect", "Multiselect\Multiselect.csproj", "{E81053F1-ACE1-4439-BA6A-162E3EA4E407}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewWindow", "NewWindow\NewWindow.csproj", "{F6734731-8849-4D1E-A1CF-95CF091E3EC3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OneWaySeq", "OneWaySeq\OneWaySeq.csproj", "{C2932EB2-16DF-48D8-8044-4A517815AF50}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleCounter", "SingleCounter\SingleCounter.csproj", "{96A6B550-E41C-4029-9D24-D1B1AD60954B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sticky", "Sticky\Sticky.csproj", "{0E7F8A17-5F75-434C-B0A7-EC83783E9BB8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubModel", "SubModel\SubModel.csproj", "{6D0A8947-5A9D-4A50-AC0C-D797EE87640B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubModelOpt", "SubModelOpt\SubModelOpt.csproj", "{F0069157-09E3-40DD-97D6-B5A3D3C42C8B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubModelSelectedItem", "SubModelSelectedItem\SubModelSelectedItem.csproj", "{FC4518FB-73DD-480B-B652-61F8CD20255B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubModelSeq", "SubModelSeq\SubModelSeq.csproj", "{5B197AC6-9D9A-46A9-B3E8-DC33AB855159}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubModelStatic", "SubModelStatic\SubModelStatic.csproj", "{D345CFDA-A4C8-4FFD-A1BD-97BBB4291189}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Threading", "Threading\Threading.csproj", "{1E9C54A2-B9DD-4F97-85B9-0DF52FD3202A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UiBoundCmdParam", "UiBoundCmdParam\UiBoundCmdParam.csproj", "{C75025E1-20AA-4F16-820E-E7B184D7DFBC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Validation", "Validation\Validation.csproj", "{1B62316F-F093-443F-ACF4-68CC21E89E23}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {11D2A55F-9315-4538-B3E4-44868816E81C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {11D2A55F-9315-4538-B3E4-44868816E81C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {11D2A55F-9315-4538-B3E4-44868816E81C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {11D2A55F-9315-4538-B3E4-44868816E81C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {26B784E2-4A97-49CB-9DD2-AD23F85A999D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26B784E2-4A97-49CB-9DD2-AD23F85A999D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26B784E2-4A97-49CB-9DD2-AD23F85A999D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26B784E2-4A97-49CB-9DD2-AD23F85A999D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {49005859-27DB-4A96-B80F-2C15AFF1A828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {49005859-27DB-4A96-B80F-2C15AFF1A828}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {49005859-27DB-4A96-B80F-2C15AFF1A828}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {49005859-27DB-4A96-B80F-2C15AFF1A828}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E366BD6-1750-4150-A6AC-2615551E0E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E366BD6-1750-4150-A6AC-2615551E0E51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E366BD6-1750-4150-A6AC-2615551E0E51}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E366BD6-1750-4150-A6AC-2615551E0E51}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E81053F1-ACE1-4439-BA6A-162E3EA4E407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E81053F1-ACE1-4439-BA6A-162E3EA4E407}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E81053F1-ACE1-4439-BA6A-162E3EA4E407}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E81053F1-ACE1-4439-BA6A-162E3EA4E407}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F6734731-8849-4D1E-A1CF-95CF091E3EC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F6734731-8849-4D1E-A1CF-95CF091E3EC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F6734731-8849-4D1E-A1CF-95CF091E3EC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F6734731-8849-4D1E-A1CF-95CF091E3EC3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2932EB2-16DF-48D8-8044-4A517815AF50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2932EB2-16DF-48D8-8044-4A517815AF50}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2932EB2-16DF-48D8-8044-4A517815AF50}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2932EB2-16DF-48D8-8044-4A517815AF50}.Release|Any CPU.Build.0 = Release|Any CPU
+ {96A6B550-E41C-4029-9D24-D1B1AD60954B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {96A6B550-E41C-4029-9D24-D1B1AD60954B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {96A6B550-E41C-4029-9D24-D1B1AD60954B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {96A6B550-E41C-4029-9D24-D1B1AD60954B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0E7F8A17-5F75-434C-B0A7-EC83783E9BB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0E7F8A17-5F75-434C-B0A7-EC83783E9BB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0E7F8A17-5F75-434C-B0A7-EC83783E9BB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0E7F8A17-5F75-434C-B0A7-EC83783E9BB8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D0A8947-5A9D-4A50-AC0C-D797EE87640B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D0A8947-5A9D-4A50-AC0C-D797EE87640B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D0A8947-5A9D-4A50-AC0C-D797EE87640B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D0A8947-5A9D-4A50-AC0C-D797EE87640B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F0069157-09E3-40DD-97D6-B5A3D3C42C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0069157-09E3-40DD-97D6-B5A3D3C42C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0069157-09E3-40DD-97D6-B5A3D3C42C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0069157-09E3-40DD-97D6-B5A3D3C42C8B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC4518FB-73DD-480B-B652-61F8CD20255B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC4518FB-73DD-480B-B652-61F8CD20255B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC4518FB-73DD-480B-B652-61F8CD20255B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC4518FB-73DD-480B-B652-61F8CD20255B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5B197AC6-9D9A-46A9-B3E8-DC33AB855159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B197AC6-9D9A-46A9-B3E8-DC33AB855159}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B197AC6-9D9A-46A9-B3E8-DC33AB855159}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B197AC6-9D9A-46A9-B3E8-DC33AB855159}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D345CFDA-A4C8-4FFD-A1BD-97BBB4291189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D345CFDA-A4C8-4FFD-A1BD-97BBB4291189}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D345CFDA-A4C8-4FFD-A1BD-97BBB4291189}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D345CFDA-A4C8-4FFD-A1BD-97BBB4291189}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1E9C54A2-B9DD-4F97-85B9-0DF52FD3202A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1E9C54A2-B9DD-4F97-85B9-0DF52FD3202A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1E9C54A2-B9DD-4F97-85B9-0DF52FD3202A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1E9C54A2-B9DD-4F97-85B9-0DF52FD3202A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C75025E1-20AA-4F16-820E-E7B184D7DFBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C75025E1-20AA-4F16-820E-E7B184D7DFBC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C75025E1-20AA-4F16-820E-E7B184D7DFBC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C75025E1-20AA-4F16-820E-E7B184D7DFBC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1B62316F-F093-443F-ACF4-68CC21E89E23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1B62316F-F093-443F-ACF4-68CC21E89E23}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1B62316F-F093-443F-ACF4-68CC21E89E23}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1B62316F-F093-443F-ACF4-68CC21E89E23}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {EAE8C9E3-06B3-4889-8E00-600FB55BEA5E}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Samples/SubModelSelectedItem.Core/Program.fs b/src/Samples/SubModelSelectedItem.Core/Program.fs
index c8f970af..bc62051b 100644
--- a/src/Samples/SubModelSelectedItem.Core/Program.fs
+++ b/src/Samples/SubModelSelectedItem.Core/Program.fs
@@ -1,57 +1,523 @@
-module Elmish.WPF.Samples.SubModelSelectedItem.Program
+namespace Program
open System
+open Elmish
+open Elmish.WPF
open Serilog
open Serilog.Extensions.Logging
-open Elmish.WPF
+open System.Windows.Media
+
+
+[]
+module Helpers =
+
+ //• logging
+ let createDashedLine () = String.replicate 69 "-"
+ let logDashedLine = createDashedLine ()
+
+
+ let generateName (prefix: string) =
+ let randomNumber () = Random().Next(1000, 10000).ToString()
+ prefix + randomNumber ()
+
+
+
+module TextBox =
+
+ type Model = { Id: Guid; Text: string }
+
+ let create () =
+ { Id = Guid.NewGuid()
+ Text = generateName "TextBox_" }
+
+ type Msg = | Dummy
+
+ let init () = create ()
+
+ let update msg m =
+ match msg with
+ | Dummy -> m
+
+
+module CheckBox =
+
+ type Model = { Id: Guid; Label: string }
+
+ let create () =
+ { Id = Guid.NewGuid()
+ Label = generateName "CheckBox_" }
+
+ type Msg = | Dummy
+
+ let init () = create ()
+
+ let update msg m =
+ match msg with
+ | Dummy -> m
+
+
+module ComboBox =
+
+ type Model =
+ { Id: Guid
+ Header: string
+ Items: string list
+ SelectedItem: string option }
+
+ let create () =
+ { Id = Guid.NewGuid()
+ Header = generateName "ComboBox_"
+ Items = [ "Option1"; "Option2"; "Option3" ]
+ SelectedItem = None }
+
+ type Msg = SelectItem of string option
+
+ let init () = create ()
+
+ let update msg m =
+ match msg with
+ | SelectItem item -> { m with SelectedItem = item }
+
+
+//# Form Designer
+module App =
+
+ type FormComponent =
+ | TextBox of TextBox.Model
+ | CheckBox of CheckBox.Model
+ | ComboBox of ComboBox.Model
+
+ type Model =
+ { Components: FormComponent list
+ PreviousSelectedFormComponent: Guid option
+ SelectedFormComponent: Guid option
+ Log: string list }
+
+ module ModelM =
+ module Components =
+ let get m = m.Components
+
+ type Msg =
+ | SelectFormComponent of Guid option
+ | AddTextBox
+ | AddCheckBox
+ | AddComboBox
+ | RemoveComponent of Guid
+ | ClearLog
+ //• SubModels
+ | TextBox_Msg of Guid * TextBox.Msg
+ | CheckBox_Msg of Guid * CheckBox.Msg
+ | ComboBox_Msg of Guid * ComboBox.Msg
+
+ let componentsMock =
+ [ TextBox(TextBox.create ())
+ CheckBox(CheckBox.create ())
+ TextBox(TextBox.create ())
+ CheckBox(CheckBox.create ())
+ ComboBox(ComboBox.create ()) ]
+
+
+ let getId (fc: FormComponent) =
+ match fc with
+ | TextBox tb -> tb.Id
+ | CheckBox cb -> cb.Id
+ | ComboBox cb -> cb.Id
+
+ let init () =
+ { Components = componentsMock
+ SelectedFormComponent = Some(getId (List.item 3 componentsMock))
+ PreviousSelectedFormComponent = None
+ Log = [] },
+ Cmd.none
+
+
+ []
+ module private UpdateHelpers =
+ //🞍 common
+ let insertAt index item list =
+ let before, after = List.splitAt index list
+ before @ [ item ] @ after
+
+
+ let getComponentName fc =
+ match fc with
+ | TextBox tb -> tb.Text
+ | CheckBox cb -> cb.Label
+ | ComboBox cb -> cb.Header
+
+
+ let selectFormComponent id m =
+ let logEntry =
+ match id with
+ | Some selectedId ->
+ match m.Components
+ |> List.tryFind (fun c -> getId c = selectedId)
+ with
+ | Some c ->
+ let name = getComponentName c
+ sprintf "Selected: %s" name
+ | None -> "Selected: Unknown component"
+ | None -> "Deselected"
+
+ { m with
+ SelectedFormComponent = id
+ Log = logEntry :: logDashedLine :: m.Log }
+
+
+ //🞍 add/remove
+ let addTextBox m =
+ let newTextBox = TextBox.create ()
+
+ let updatedTextBox = { newTextBox with Text = "###New### --- " + newTextBox.Text }
+
+ let newComponent = TextBox updatedTextBox
+
+ let components =
+ match m.SelectedFormComponent with
+ | Some selectedId ->
+ match m.Components
+ |> List.tryFindIndex (fun c -> getId c = selectedId)
+ with
+ | Some index -> insertAt (index + 1) newComponent m.Components
+ | None -> m.Components @ [ newComponent ]
+ | None -> m.Components @ [ newComponent ]
+
+ let log =
+ ("Added: " + updatedTextBox.Text)
+ :: ("Selected: " + updatedTextBox.Text)
+ :: logDashedLine :: m.Log
+
+ { m with
+ Components = components
+ SelectedFormComponent = Some(getId newComponent)
+ Log = log }
+
+
+ let addCheckBox m =
+ let newCheckBox = CheckBox.create ()
+
+ let updatedCheckBox = { newCheckBox with Label = "###New### --- " + newCheckBox.Label }
+
+ let newComponent = CheckBox updatedCheckBox
+
+ let components =
+ match m.SelectedFormComponent with
+ | Some selectedId ->
+ match m.Components
+ |> List.tryFindIndex (fun c -> getId c = selectedId)
+ with
+ | Some index -> insertAt (index + 1) newComponent m.Components
+ | None -> m.Components @ [ newComponent ]
+ | None -> m.Components @ [ newComponent ]
+
+ let log =
+ ("Added: " + updatedCheckBox.Label)
+ :: ("Selected: " + updatedCheckBox.Label)
+ :: logDashedLine :: m.Log
+
+ { m with
+ Components = components
+ SelectedFormComponent = Some(getId newComponent)
+ Log = log }
+
+
+ let addComboBox m =
+ let newComboBox = ComboBox.create ()
+
+ let updateComboBox = { newComboBox with Header = "###New### --- " + newComboBox.Header }
+
+ let newComponent = ComboBox newComboBox
+
+ let components =
+ match m.SelectedFormComponent with
+ | Some selectedId ->
+ match m.Components
+ |> List.tryFindIndex (fun c -> getId c = selectedId)
+ with
+ | Some index -> insertAt (index + 1) newComponent m.Components
+ | None -> m.Components @ [ newComponent ]
+ | None -> m.Components @ [ newComponent ]
+
+ let log =
+ ("Added: " + updateComboBox.Header)
+ :: ("Selected: " + updateComboBox.Header)
+ :: logDashedLine :: m.Log
+
+ { m with
+ Components = components
+ SelectedFormComponent = Some(getId newComponent)
+ Log = log }
+
+
+ let removeComponent id m : Model * Guid option * string list =
+ let componentOpt =
+ m.Components
+ |> List.tryFind (fun c -> getId c = id)
+
+ let removedComponentName =
+ match componentOpt with
+ | Some c -> getComponentName c
+ | None -> "Unknown Component"
+
+ let idxOpt =
+ m.Components
+ |> List.tryFindIndex (fun c -> getId c = id)
+
+ let components = List.filter (fun c -> getId c <> id) m.Components
+
+ let newSelected =
+ match idxOpt with
+ | Some idx when idx > 0 -> Some(getId (List.item (idx - 1) m.Components))
+ | Some idx when components.Length > 0 -> Some(getId (List.item 0 components))
+ | _ -> None
+
+ let logs = [ "Removed: " + removedComponentName ]
+
+ let m' = { m with Components = components }
+
+ m', newSelected, logs
+
+
+ //🞍 SubModels
+ // maybe refactor later
+ let textBox_Msg (id, msg) m =
+ let updateComponent c =
+ match c with
+ | TextBox tb when tb.Id = id -> TextBox(TextBox.update msg tb)
+ | other -> other
+
+ { m with Components = List.map updateComponent m.Components }
+
+
+ let checkBox_Msg (id, msg) m =
+ let updateComponent c =
+ match c with
+ | CheckBox cb when cb.Id = id -> CheckBox(CheckBox.update msg cb)
+ | other -> other
+
+ { m with Components = List.map updateComponent m.Components }
+
+
+ let comboBox_Msg (id, msg) m =
+ let updateComponent c =
+ match c with
+ | ComboBox cb when cb.Id = id -> ComboBox(ComboBox.update msg cb)
+ | other -> other
+
+ { m with Components = List.map updateComponent m.Components }
+
+
+ let update msg m : Model * Cmd =
+ match msg with
+ | SelectFormComponent id ->
+ let m' = selectFormComponent id m
+ m', Cmd.none
+ | AddTextBox ->
+ let m' = addTextBox m
+ m', Cmd.none
+ | AddCheckBox ->
+ let m' = addCheckBox m
+ m', Cmd.none
+ | AddComboBox ->
+ let m' = addComboBox m
+ m', Cmd.none
+ | RemoveComponent id ->
+ let m', newSelectedId, logs = removeComponent id m
+ let cmd = Cmd.ofMsg (SelectFormComponent newSelectedId)
+ let m'' = { m' with Log = logs @ m'.Log }
+ m'', cmd
+ | ClearLog -> { m with Log = [] }, Cmd.none
+ // SubModels
+ | TextBox_Msg (id, msg) ->
+ let m' = textBox_Msg (id, msg) m
+ m', Cmd.none
+ | CheckBox_Msg (id, msg) ->
+ let m' = checkBox_Msg (id, msg) m
+ m', Cmd.none
+ | ComboBox_Msg (id, msg) ->
+ let m' = comboBox_Msg (id, msg) m
+ m', Cmd.none
+
+
+[]
+type TextBox_VM(args) =
+ inherit ViewModelBase(args)
+
+ //• helpers
+
+ //🅦 TextBox add ctor? TRY MAYBE IT DOEST WORK BECAUSE OF THIS
+ new() = TextBox_VM(TextBox.init () |> ViewModelArgs.simple)
+
+ //• members
+ member _.Text = base.Get () (Binding.oneWay ((fun m -> m.Text)))
+
+
+[]
+type CheckBox_VM(args) =
+ inherit ViewModelBase(args)
+
+ //• helpers
+ new() = CheckBox_VM(CheckBox.init () |> ViewModelArgs.simple)
+
+ //• members
+ member _.Label = base.Get () (Binding.oneWay ((fun m -> m.Label)))
+
+
+[]
+type ComboBox_VM(args) =
+ inherit ViewModelBase(args)
+
+ new() = ComboBox_VM(ComboBox.init () |> ViewModelArgs.simple)
+
+ member _.Items = base.Get () (Binding.oneWay (fun m -> m.Items))
+ member _.Header = base.Get () (Binding.oneWay (fun m -> m.Header))
+
+ member _.SelectedItem
+ with get () =
+ base.Get
+ ()
+ (Binding.twoWay ((fun (m: ComboBox.Model) -> m.SelectedItem), (fun v _ -> ComboBox.Msg.SelectItem v)))
+ and set (value) =
+ base.Set
+ (value)
+ (Binding.twoWay ((fun (m: ComboBox.Model) -> m.SelectedItem), (fun v _ -> ComboBox.Msg.SelectItem v)))
+
+
+[]
+type FormComponent_VM(args: ViewModelArgs) =
+ inherit ViewModelBase(args)
+
+ member this.CurrentModel =
+ (this :> IViewModel)
+ .CurrentModel
+
+ member this.Model = fst this.CurrentModel
+ member this.FormComponent = snd this.CurrentModel
+
+ member this.Id =
+ match this.FormComponent with
+ | App.FormComponent.TextBox tb -> tb.Id
+ | App.FormComponent.CheckBox cb -> cb.Id
+ | App.FormComponent.ComboBox cb -> cb.Id
+
+ member this.ComponentVM: obj =
+ let id = this.Id
+
+ match this.FormComponent with
+ | App.FormComponent.TextBox tb ->
+ upcast TextBox_VM(ViewModelArgs.map (fun _ -> tb) (fun msg -> App.Msg.TextBox_Msg(id, msg)) args)
+ | App.FormComponent.CheckBox cb ->
+ upcast CheckBox_VM(ViewModelArgs.map (fun _ -> cb) (fun msg -> App.Msg.CheckBox_Msg(id, msg)) args)
+ | App.FormComponent.ComboBox cb ->
+ upcast ComboBox_VM(ViewModelArgs.map (fun _ -> cb) (fun msg -> App.Msg.ComboBox_Msg(id, msg)) args)
+
+ member this.SelectedLabel =
+ let componentId = this.Id
+
+ base.Get
+ ()
+ (Binding.oneWay (fun (m, _) ->
+ if Some componentId = m.SelectedFormComponent then
+ " • Selected"
+ else
+ ""))
+
+
+ // can be done in XAML using lots of boilerplate
+ // I guess that since it's in a ViewModel, there is no "separation of concerns" issues
+ //# what do you think?
+ member this.BackgroundColor: Brush =
+ match this.FormComponent with
+ | App.FormComponent.TextBox _ -> Brushes.DarkGreen
+ | App.FormComponent.CheckBox _ -> Brushes.DarkRed
+ | App.FormComponent.ComboBox _ -> Brushes.DarkOrange
+
+
+// Adjusted App_VM with SelectedComponent having both get and set
+[]
+type App_VM(args) =
+ inherit ViewModelBase(args)
+
+ let getId ((_, fc): App.Model * App.FormComponent) =
+ match fc with
+ | App.FormComponent.TextBox tb -> tb.Id
+ | App.FormComponent.CheckBox cb -> cb.Id
+ | App.FormComponent.ComboBox cb -> cb.Id
+
+
+ new() = App_VM((App.init () |> fst) |> ViewModelArgs.simple)
+
+
+ member _.Components_VM =
+ base.Get
+ ()
+ (Binding.SubModelSeqKeyedT.id (fun args -> FormComponent_VM(args)) getId
+ >> Binding.mapModel (fun (m: App.Model) -> m.Components |> List.map (fun fc -> (m, fc)))
+ >> Binding.addLazy (fun m1 m2 ->
+ m1.SelectedFormComponent = m2.SelectedFormComponent
+ && m1.Components = m2.Components)
+ >> Binding.mapMsg (fun (_id, msg) -> msg))
+
+
+
+ member _.SelectedComponent
+ with get () =
+ base.Get
+ ()
+ (Binding.subModelSelectedItem (
+ "Components_VM",
+ (fun (m: App.Model) -> m.SelectedFormComponent),
+ App.Msg.SelectFormComponent
+ ))
+ and set value =
+ base.Set
+ (value)
+ (Binding.subModelSelectedItem (
+ "Components_VM",
+ (fun (m: App.Model) -> m.SelectedFormComponent),
+ App.Msg.SelectFormComponent
+ ))
+
-type Entity =
- { Id: int
- Name: string }
-type Model =
- { Entities: Entity list
- Selected: int option }
+ member _.AddTextBox = base.Get () (Binding.CmdT.setAlways App.Msg.AddTextBox)
+ member _.AddCheckBox = base.Get () (Binding.CmdT.setAlways App.Msg.AddCheckBox)
+ member _.AddComboBox = base.Get () (Binding.CmdT.setAlways App.Msg.AddComboBox)
+ member _.ClearLog = base.Get () (Binding.CmdT.setAlways App.Msg.ClearLog)
-let init () =
- { Entities = [0 .. 10] |> List.map (fun i -> { Id = i; Name = sprintf "Entity %i" i})
- Selected = Some 4 }
-type Msg =
- | Select of int option
+ member _.RemoveSelectedComponent =
+ base.Get
+ ()
+ (Binding.cmdIf (fun (m: App.Model) ->
+ match m.SelectedFormComponent with
+ | Some id -> App.Msg.RemoveComponent id |> ValueSome
+ | None -> ValueNone))
-let update msg m =
- match msg with
- | Select entityId -> { m with Selected = entityId }
-let bindings () : Binding list = [
- "SelectRandom" |> Binding.cmd
- (fun m -> m.Entities.Item(Random().Next(m.Entities.Length)).Id |> Some |> Select)
- "Deselect" |> Binding.cmd(Select None)
+ //🅦 review it (put in update?)
+ member _.Log =
+ base.Get
+ ()
+ (Binding.oneWay (fun m ->
+ let logLength = List.length m.Log
+ let takeCount = min 40 logLength
+ String.concat "\n" (List.take takeCount m.Log)))
- "Entities" |> Binding.subModelSeq(
- (fun m -> m.Entities),
- (fun e -> e.Id),
- (fun () -> [
- "Name" |> Binding.oneWay (fun (_, e) -> e.Name)
- "SelectedLabel" |> Binding.oneWay (fun (m, e) -> if m.Selected = Some e.Id then " - SELECTED" else "")
- ]))
- "SelectedEntity" |> Binding.subModelSelectedItem("Entities", (fun m -> m.Selected), Select)
-]
+module Program =
-let designVm = ViewModel.designInstance (init ()) (bindings ())
+ let main (window) =
-let main window =
- let logger =
- LoggerConfiguration()
- .MinimumLevel.Override("Elmish.WPF.Update", Events.LogEventLevel.Verbose)
- .MinimumLevel.Override("Elmish.WPF.Bindings", Events.LogEventLevel.Verbose)
- .MinimumLevel.Override("Elmish.WPF.Performance", Events.LogEventLevel.Verbose)
- .WriteTo.Console()
- .CreateLogger()
+ let logger =
+ LoggerConfiguration()
+ .MinimumLevel.Override("Elmish.WPF.Update", Events.LogEventLevel.Verbose)
+ .MinimumLevel.Override("Elmish.WPF.Bindings", Events.LogEventLevel.Verbose)
+ .MinimumLevel.Override("Elmish.WPF.Performance", Events.LogEventLevel.Verbose)
+ .WriteTo.Console()
+ .CreateLogger()
- WpfProgram.mkSimple init update bindings
- |> WpfProgram.withLogger (new SerilogLoggerFactory(logger))
- |> WpfProgram.startElmishLoop window
+ WpfProgram.mkProgramT App.init App.update App_VM
+ |> WpfProgram.withLogger (new SerilogLoggerFactory(logger))
+ |> WpfProgram.startElmishLoop window
diff --git a/src/Samples/SubModelSelectedItem.Core/SubModelSelectedItem.Core.fsproj b/src/Samples/SubModelSelectedItem.Core/SubModelSelectedItem.Core.fsproj
index 28983b0f..8c5aa9d0 100644
--- a/src/Samples/SubModelSelectedItem.Core/SubModelSelectedItem.Core.fsproj
+++ b/src/Samples/SubModelSelectedItem.Core/SubModelSelectedItem.Core.fsproj
@@ -1,25 +1,19 @@
-
-
+true
-
net8.0-windows
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/Samples/SubModelSelectedItem/App.xaml.cs b/src/Samples/SubModelSelectedItem/App.xaml.cs
index 15195c44..b02a9c86 100644
--- a/src/Samples/SubModelSelectedItem/App.xaml.cs
+++ b/src/Samples/SubModelSelectedItem/App.xaml.cs
@@ -3,18 +3,18 @@
namespace Elmish.WPF.Samples.SubModelSelectedItem
{
- public partial class App : Application
- {
- public App()
+ public partial class App : Application
{
- this.Activated += StartElmish;
- }
+ public App()
+ {
+ this.Activated += StartElmish;
+ }
- private void StartElmish(object sender, EventArgs e)
- {
- this.Activated -= StartElmish;
- Program.main(MainWindow);
- }
+ private void StartElmish(object sender, EventArgs e)
+ {
+ this.Activated -= StartElmish;
+ Program.Program.main(MainWindow);
+ }
- }
+ }
}
diff --git a/src/Samples/SubModelSelectedItem/MainWindow.xaml b/src/Samples/SubModelSelectedItem/MainWindow.xaml
index a2702e7c..5156d45a 100644
--- a/src/Samples/SubModelSelectedItem/MainWindow.xaml
+++ b/src/Samples/SubModelSelectedItem/MainWindow.xaml
@@ -1,29 +1,143 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Samples/SubModelSelectedItem/MainWindow.xaml.cs b/src/Samples/SubModelSelectedItem/MainWindow.xaml.cs
index 3a47308a..7fe8eaeb 100644
--- a/src/Samples/SubModelSelectedItem/MainWindow.xaml.cs
+++ b/src/Samples/SubModelSelectedItem/MainWindow.xaml.cs
@@ -7,6 +7,13 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
+ PreviewKeyDown += (sender, e) =>
+ {
+ if (e.Key == System.Windows.Input.Key.Escape)
+ {
+ Close();
+ }
+ };
}
}
}