Skip to content

Instantly share code, notes, and snippets.

@kleidemos
Last active March 8, 2019 09:17
Show Gist options
  • Save kleidemos/f925b9744e98f4ee039ff9ce1f1e8cd3 to your computer and use it in GitHub Desktop.
Save kleidemos/f925b9744e98f4ee039ff9ce1f1e8cd3 to your computer and use it in GitHub Desktop.
namespace Gjallarhorn.Bindable
open Gjallarhorn
open Gjallarhorn.Bindable
open Gjallarhorn.Helpers
open System
open System.Windows.Input
type internal ManagedParameterCommand<'a> (allowExecute : ISignal<'a -> bool>) as self =
let source = Event<'a>()
let disposeTracker = new CompositeDisposable()
do allowExecute
|> Signal.Subscription.create (fun _ -> self.RaiseCanExecuteChanged())
|> disposeTracker.Add
member this.RaiseCanExecuteChanged() =
CommandManager.InvalidateRequerySuggested()
abstract member HandleExecute : obj -> unit
default this.HandleExecute(param : obj) =
tryUnbox param
|> Option.iter source.Trigger
abstract member HandleCanExecute : obj -> bool
default this.HandleCanExecute param =
tryUnbox<'a> param
|> Option.exists allowExecute.Value
interface IDisposable with
member __.Dispose () = disposeTracker.Dispose()
interface IObservable<'a> with
member this.Subscribe obs = source.Publish.Subscribe obs
interface ITrackingCommand<'a>
interface ICommand with
[<CLIEvent>]
member __.CanExecuteChanged = CommandManager.RequerySuggested
member this.CanExecute (parameter : obj) = this.HandleCanExecute parameter
member this.Execute(param : obj) = this.HandleExecute(param)
module Command =
let createManagedParam<'a> enabledSource =
new ManagedParameterCommand<'a>(enabledSource)
:> ITrackingCommand<'a>
module Bind =
module Explicit =
let createManagedCommandParamChecked<'a> name (source : BindingSource) canExecute =
let command = Command.createManagedParam<'a> canExecute
source.AddDisposable command
source.ConstantToView (command, name)
command
// CanExecute return false if parameter is null or wrong type.
let createManagedCommandParam name source =
Signal.constant (fun _ -> true)
|> createManagedCommandParamChecked name source
let createManagedMessageParamChecked name createMessage source canExecute =
createManagedCommandParamChecked name source canExecute
|> Observable.map createMessage
// CanExecute return false if parameter is null or wrong type.
let createManagedMessageParam name message source =
Signal.constant (fun _ -> true)
|> createManagedMessageParamChecked
name
message
source
open Microsoft.FSharp.Quotations
let cmdManagedParamIf<'Model, 'Nav, 'Param, 'Msg when 'Model : equality> canExecute (setter : 'Param -> 'Msg) (name : Expr<VmCmd<'Msg>>) =
fun (_ : Dispatch<'Nav>) (source : BindingSource) (signal : ISignal<'Model>) ->
signal
|> Signal.map canExecute
|> Explicit.createManagedMessageParamChecked (nameof name) setter source
|> Some
let cmdManagedParam<'Model, 'Nav, 'Param, 'Msg> setter name =
fun (_ : Dispatch<'Nav>) (source : BindingSource) (_ : ISignal<'Model>) ->
Explicit.createManagedMessageParam (nameof name) setter source
|> Some
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment