Skip to content

Commit 3b828cb

Browse files
committed
Get rid of Typed refs so that this can be mapped / boxed
1 parent 08d24c9 commit 3b828cb

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

src/Elmish.WPF/BindingVmHelpers.fs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,16 @@ type TwoWayBinding<'model, 'a> = {
107107

108108
type SubModelBinding<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm> = {
109109
SubModelData: SubModelData<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm>
110-
Vm: 'vm voption ref
110+
GetVm: unit -> 'vm voption
111+
SetVm: 'vm voption -> unit
111112
}
112113

113114
type SubModelWinBinding<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm> = {
114115
SubModelWinData: SubModelWinData<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm>
115116
WinRef: WeakReference<Window>
116117
PreventClose: bool ref
117-
VmWinState: WindowState<'vm> ref
118+
GetVmWinState: unit -> WindowState<'vm>
119+
SetVmWinState: WindowState<'vm> -> unit
118120
}
119121

120122
type SubModelSeqUnkeyedBinding<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm, 'vmCollection> = {
@@ -163,7 +165,8 @@ type BaseVmBinding<'model, 'msg, 'a> =
163165

164166
type CachedBinding<'model, 'msg, 'a> = {
165167
Binding: VmBinding<'model, 'msg, 'a>
166-
Cache: 'a option ref
168+
GetCache: unit -> 'a option
169+
SetCache: 'a option -> unit
167170
}
168171

169172
and ValidationBinding<'model, 'msg, 'a> = {
@@ -195,7 +198,7 @@ and VmBinding<'model, 'msg, 'a> =
195198

196199
with
197200

198-
member this.AddCaching = Cached { Binding = this; Cache = ref None }
201+
member this.AddCaching = let mutable cache = None in Cached { Binding = this; GetCache = (fun () -> cache); SetCache = fun c -> cache <- c }
199202
member this.AddValidation currentModel validate =
200203
{ Binding = this
201204
Validate = validate
@@ -314,18 +317,20 @@ type Initialize<'a>
314317
d.GetModel initialModel
315318
|> ValueOption.map (fun m -> ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs)
316319
|> ValueOption.map d.CreateViewModel
317-
|> (fun vm -> { SubModelData = d; Vm = ref vm })
320+
|> (fun vm -> let mutable vm = vm in { SubModelData = d; GetVm = (fun () -> vm); SetVm = fun nvm -> vm <- nvm })
318321
|> SubModel
319322
|> Some
320323
| SubModelWinData d ->
321324
let d = d |> BindingData.SubModelWin.measureFunctions measure measure measure2
322325
let toMsg = fun msg -> d.ToMsg (getCurrentModel ()) msg
323326
match d.GetState initialModel with
324327
| WindowState.Closed ->
328+
let mutable vmWinState = WindowState.Closed
325329
{ SubModelWinData = d
326330
WinRef = WeakReference<_>(null)
327331
PreventClose = ref true
328-
VmWinState = ref WindowState.Closed }
332+
GetVmWinState = fun () -> vmWinState
333+
SetVmWinState = fun vmState -> vmWinState <- vmState }
329334
| WindowState.Hidden m ->
330335
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
331336
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -334,10 +339,12 @@ type Initialize<'a>
334339
let preventClose = ref true
335340
log.LogTrace("[{BindingNameChain}] Creating hidden window", chain)
336341
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Hidden getCurrentModel dispatch
342+
let mutable vmWinState = WindowState.Hidden vm
337343
{ SubModelWinData = d
338344
WinRef = winRef
339345
PreventClose = preventClose
340-
VmWinState = ref <| WindowState.Hidden vm }
346+
GetVmWinState = fun () -> vmWinState
347+
SetVmWinState = fun vm -> vmWinState <- vm }
341348
| WindowState.Visible m ->
342349
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
343350
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -346,10 +353,12 @@ type Initialize<'a>
346353
let preventClose = ref true
347354
log.LogTrace("[{BindingNameChain}] Creating visible window", chain)
348355
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Visible getCurrentModel dispatch
356+
let mutable vmWinState = WindowState.Visible vm
349357
{ SubModelWinData = d
350358
WinRef = winRef
351359
PreventClose = preventClose
352-
VmWinState = ref <| WindowState.Visible vm }
360+
GetVmWinState = fun () -> vmWinState
361+
SetVmWinState = fun vm -> vmWinState <- vm }
353362
|> SubModelWin
354363
|> Some
355364
| SubModelSeqUnkeyedData d ->
@@ -459,16 +468,16 @@ type Update
459468
| Cmd cmd -> cmd |> CanExecuteChanged |> List.singleton
460469
| SubModel b ->
461470
let d = b.SubModelData
462-
match b.Vm.Value, d.GetModel newModel with
471+
match b.GetVm (), d.GetModel newModel with
463472
| ValueNone, ValueNone -> []
464473
| ValueSome _, ValueNone ->
465-
b.Vm.Value <- ValueNone
474+
b.SetVm ValueNone
466475
[ PropertyChanged name ]
467476
| ValueNone, ValueSome m ->
468477
let toMsg = fun msg -> d.ToMsg (getCurrentModel ()) msg
469478
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
470479
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
471-
b.Vm.Value <- ValueSome <| d.CreateViewModel(args)
480+
b.SetVm (ValueSome <| d.CreateViewModel(args))
472481
[ PropertyChanged name ]
473482
| ValueSome vm, ValueSome m ->
474483
d.UpdateViewModel (vm, m)
@@ -519,7 +528,7 @@ type Update
519528
let args = ViewModelArgs.create model (toMsg >> dispatch) chain loggingArgs
520529
d.CreateViewModel args
521530

522-
match b.VmWinState.Value, d.GetState newModel with
531+
match b.GetVmWinState(), d.GetState newModel with
523532
| WindowState.Closed, WindowState.Closed ->
524533
[]
525534
| WindowState.Hidden vm, WindowState.Hidden m
@@ -529,29 +538,29 @@ type Update
529538
| WindowState.Hidden _, WindowState.Closed
530539
| WindowState.Visible _, WindowState.Closed ->
531540
close ()
532-
b.VmWinState.Value <- WindowState.Closed
541+
b.SetVmWinState WindowState.Closed
533542
[ PropertyChanged name ]
534543
| WindowState.Visible vm, WindowState.Hidden m ->
535544
hide ()
536545
d.UpdateViewModel (vm, m)
537-
b.VmWinState.Value <- WindowState.Hidden vm
546+
b.SetVmWinState (WindowState.Hidden vm)
538547
[]
539548
| WindowState.Hidden vm, WindowState.Visible m ->
540549
d.UpdateViewModel (vm, m)
541550
showHidden ()
542-
b.VmWinState.Value <- WindowState.Visible vm
551+
b.SetVmWinState (WindowState.Visible vm)
543552
[]
544553
| WindowState.Closed, WindowState.Hidden m ->
545554
let vm = newVm m
546555
log.LogTrace("[{BindingNameChain}] Creating hidden window", winPropChain)
547556
showNew vm Visibility.Hidden getCurrentModel dispatch
548-
b.VmWinState.Value <- WindowState.Hidden vm
557+
b.SetVmWinState (WindowState.Hidden vm)
549558
[ PropertyChanged name ]
550559
| WindowState.Closed, WindowState.Visible m ->
551560
let vm = newVm m
552561
log.LogTrace("[{BindingNameChain}] Creating visible window", winPropChain)
553562
showNew vm Visibility.Visible getCurrentModel dispatch
554-
b.VmWinState.Value <- WindowState.Visible vm
563+
b.SetVmWinState (WindowState.Visible vm)
555564
[ PropertyChanged name ]
556565
| SubModelSeqUnkeyed b ->
557566
let d = b.SubModelSeqUnkeyedData
@@ -593,7 +602,7 @@ type Update
593602
let updates = this.Recursive(currentModel, getCurrentModel, newModel, dispatch, b.Binding)
594603
updates
595604
|> List.filter UpdateData.isPropertyChanged
596-
|> List.iter (fun _ -> b.Cache.Value <- None)
605+
|> List.iter (fun _ -> b.SetCache None)
597606
updates
598607
| Validatation b ->
599608
let updates = this.Recursive(currentModel, getCurrentModel, newModel, dispatch, b.Binding)
@@ -623,12 +632,12 @@ type Get<'a>(nameChain: string) =
623632
| OneWayToSource _ -> GetError.OneWayToSource |> Error
624633
| OneWaySeq { Values = vals } -> vals.BoxedCollection() |> Ok
625634
| Cmd cmd -> cmd |> unbox |> Ok
626-
| SubModel { Vm = vm } ->
627-
vm.Value
635+
| SubModel { GetVm = getvm } ->
636+
getvm()
628637
|> ValueOption.toNull
629638
|> Result.mapError GetError.ToNullError
630-
| SubModelWin { VmWinState = vm } ->
631-
vm.Value
639+
| SubModelWin { GetVmWinState = getvm } ->
640+
getvm()
632641
|> WindowState.toVOption
633642
|> ValueOption.toNull
634643
|> Result.mapError GetError.ToNullError
@@ -656,11 +665,11 @@ type Get<'a>(nameChain: string) =
656665
match binding with
657666
| BaseVmBinding b -> this.Base(model, b)
658667
| Cached b ->
659-
match b.Cache.Value with
668+
match b.GetCache() with
660669
| Some v -> v |> Ok
661670
| None ->
662671
let x = this.Recursive(model, b.Binding)
663-
x |> Result.iter (fun v -> b.Cache.Value <- Some v)
672+
x |> Result.iter (fun v -> b.SetCache (Some v))
664673
x
665674
| Validatation b -> this.Recursive(model, b.Binding)
666675
| Lazy b -> this.Recursive(b.Get model, b.Binding)

0 commit comments

Comments
 (0)