Skip to content

Commit 72c0684

Browse files
committed
Get rid of Typed refs so that this can be mapped / boxed
1 parent 271ae4e commit 72c0684

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

src/Elmish.WPF/BindingVmHelpers.fs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,16 @@ type TwoWayBinding<'model, 'a> = {
106106

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

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

119121
type SubModelSeqUnkeyedBinding<'model, 'msg, 'bindingModel, 'bindingMsg, 'vm, 'vmCollection> = {
@@ -162,7 +164,8 @@ type BaseVmBinding<'model, 'msg> =
162164

163165
type CachedBinding<'model, 'msg, 'value> = {
164166
Binding: VmBinding<'model, 'msg>
165-
Cache: 'value option ref
167+
GetCache: unit -> 'value option
168+
SetCache: 'value option -> unit
166169
}
167170

168171
and ValidationBinding<'model, 'msg> = {
@@ -194,7 +197,7 @@ and VmBinding<'model, 'msg> =
194197

195198
with
196199

197-
member this.AddCaching = Cached { Binding = this; Cache = ref None }
200+
member this.AddCaching = let mutable cache = None in Cached { Binding = this; GetCache = (fun () -> cache); SetCache = fun c -> cache <- c }
198201
member this.AddValidation currentModel validate =
199202
{ Binding = this
200203
Validate = validate
@@ -313,18 +316,20 @@ type Initialize
313316
d.GetModel initialModel
314317
|> ValueOption.map (fun m -> ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs)
315318
|> ValueOption.map d.CreateViewModel
316-
|> (fun vm -> { SubModelData = d; Vm = ref vm })
319+
|> (fun vm -> let mutable vm = vm in { SubModelData = d; GetVm = (fun () -> vm); SetVm = fun nvm -> vm <- nvm })
317320
|> SubModel
318321
|> Some
319322
| SubModelWinData d ->
320323
let d = d |> BindingData.SubModelWin.measureFunctions measure measure measure2
321324
let toMsg = fun msg -> d.ToMsg (getCurrentModel ()) msg
322325
match d.GetState initialModel with
323326
| WindowState.Closed ->
327+
let mutable vmWinState = WindowState.Closed
324328
{ SubModelWinData = d
325329
WinRef = WeakReference<_>(null)
326330
PreventClose = ref true
327-
VmWinState = ref WindowState.Closed }
331+
GetVmWinState = fun () -> vmWinState
332+
SetVmWinState = fun vmState -> vmWinState <- vmState }
328333
| WindowState.Hidden m ->
329334
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
330335
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -333,10 +338,12 @@ type Initialize
333338
let preventClose = ref true
334339
log.LogTrace("[{BindingNameChain}] Creating hidden window", chain)
335340
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Hidden getCurrentModel dispatch
341+
let mutable vmWinState = WindowState.Hidden vm
336342
{ SubModelWinData = d
337343
WinRef = winRef
338344
PreventClose = preventClose
339-
VmWinState = ref <| WindowState.Hidden vm }
345+
GetVmWinState = fun () -> vmWinState
346+
SetVmWinState = fun vm -> vmWinState <- vm }
340347
| WindowState.Visible m ->
341348
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
342349
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -345,10 +352,12 @@ type Initialize
345352
let preventClose = ref true
346353
log.LogTrace("[{BindingNameChain}] Creating visible window", chain)
347354
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Visible getCurrentModel dispatch
355+
let mutable vmWinState = WindowState.Visible vm
348356
{ SubModelWinData = d
349357
WinRef = winRef
350358
PreventClose = preventClose
351-
VmWinState = ref <| WindowState.Visible vm }
359+
GetVmWinState = fun () -> vmWinState
360+
SetVmWinState = fun vm -> vmWinState <- vm }
352361
|> SubModelWin
353362
|> Some
354363
| SubModelSeqUnkeyedData d ->
@@ -458,16 +467,16 @@ type Update
458467
| Cmd cmd -> cmd |> CanExecuteChanged |> List.singleton
459468
| SubModel b ->
460469
let d = b.SubModelData
461-
match b.Vm.Value, d.GetModel newModel with
470+
match b.GetVm (), d.GetModel newModel with
462471
| ValueNone, ValueNone -> []
463472
| ValueSome _, ValueNone ->
464-
b.Vm.Value <- ValueNone
473+
b.SetVm ValueNone
465474
[ PropertyChanged name ]
466475
| ValueNone, ValueSome m ->
467476
let toMsg = fun msg -> d.ToMsg (getCurrentModel ()) msg
468477
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
469478
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
470-
b.Vm.Value <- ValueSome <| d.CreateViewModel(args)
479+
b.SetVm (ValueSome <| d.CreateViewModel(args))
471480
[ PropertyChanged name ]
472481
| ValueSome vm, ValueSome m ->
473482
d.UpdateViewModel (vm, m)
@@ -518,7 +527,7 @@ type Update
518527
let args = ViewModelArgs.create model (toMsg >> dispatch) chain loggingArgs
519528
d.CreateViewModel args
520529

521-
match b.VmWinState.Value, d.GetState newModel with
530+
match b.GetVmWinState(), d.GetState newModel with
522531
| WindowState.Closed, WindowState.Closed ->
523532
[]
524533
| WindowState.Hidden vm, WindowState.Hidden m
@@ -528,29 +537,29 @@ type Update
528537
| WindowState.Hidden _, WindowState.Closed
529538
| WindowState.Visible _, WindowState.Closed ->
530539
close ()
531-
b.VmWinState.Value <- WindowState.Closed
540+
b.SetVmWinState WindowState.Closed
532541
[ PropertyChanged name ]
533542
| WindowState.Visible vm, WindowState.Hidden m ->
534543
hide ()
535544
d.UpdateViewModel (vm, m)
536-
b.VmWinState.Value <- WindowState.Hidden vm
545+
b.SetVmWinState (WindowState.Hidden vm)
537546
[]
538547
| WindowState.Hidden vm, WindowState.Visible m ->
539548
d.UpdateViewModel (vm, m)
540549
showHidden ()
541-
b.VmWinState.Value <- WindowState.Visible vm
550+
b.SetVmWinState (WindowState.Visible vm)
542551
[]
543552
| WindowState.Closed, WindowState.Hidden m ->
544553
let vm = newVm m
545554
log.LogTrace("[{BindingNameChain}] Creating hidden window", winPropChain)
546555
showNew vm Visibility.Hidden getCurrentModel dispatch
547-
b.VmWinState.Value <- WindowState.Hidden vm
556+
b.SetVmWinState (WindowState.Hidden vm)
548557
[ PropertyChanged name ]
549558
| WindowState.Closed, WindowState.Visible m ->
550559
let vm = newVm m
551560
log.LogTrace("[{BindingNameChain}] Creating visible window", winPropChain)
552561
showNew vm Visibility.Visible getCurrentModel dispatch
553-
b.VmWinState.Value <- WindowState.Visible vm
562+
b.SetVmWinState (WindowState.Visible vm)
554563
[ PropertyChanged name ]
555564
| SubModelSeqUnkeyed b ->
556565
let d = b.SubModelSeqUnkeyedData
@@ -592,7 +601,7 @@ type Update
592601
let updates = this.Recursive(currentModel, getCurrentModel, newModel, dispatch, b.Binding)
593602
updates
594603
|> List.filter UpdateData.isPropertyChanged
595-
|> List.iter (fun _ -> b.Cache.Value <- None)
604+
|> List.iter (fun _ -> b.SetCache None)
596605
updates
597606
| Validatation b ->
598607
let updates = this.Recursive(currentModel, getCurrentModel, newModel, dispatch, b.Binding)
@@ -622,13 +631,8 @@ type Get(nameChain: string) =
622631
| OneWayToSource _ -> GetError.OneWayToSource |> Error
623632
| OneWaySeq { Values = vals } -> vals.GetCollection () |> Ok
624633
| Cmd cmd -> cmd |> box |> Ok
625-
| SubModel { Vm = vm } -> vm.Value |> ValueOption.toObj |> box |> Ok
626-
| SubModelWin { VmWinState = vm } ->
627-
vm.Value
628-
|> WindowState.toVOption
629-
|> ValueOption.map box
630-
|> ValueOption.toObj
631-
|> Ok
634+
| SubModel { GetVm = getvm } -> getvm() |> ValueOption.toObj |> box |> Ok
635+
| SubModelWin { GetVmWinState = getvm } -> getvm() |> WindowState.toVOption |> ValueOption.map box |> ValueOption.toObj |> Ok
632636
| SubModelSeqUnkeyed { Vms = vms }
633637
| SubModelSeqKeyed { Vms = vms } -> vms.GetCollection () |> Ok
634638
| SubModelSelectedItem b ->
@@ -653,11 +657,11 @@ type Get(nameChain: string) =
653657
match binding with
654658
| BaseVmBinding b -> this.Base(model, b)
655659
| Cached b ->
656-
match b.Cache.Value with
660+
match b.GetCache() with
657661
| Some v -> v |> Ok
658662
| None ->
659663
let x = this.Recursive(model, b.Binding)
660-
x |> Result.iter (fun v -> b.Cache.Value <- Some v)
664+
x |> Result.iter (fun v -> b.SetCache (Some v))
661665
x
662666
| Validatation b -> this.Recursive(model, b.Binding)
663667
| Lazy b -> this.Recursive(b.Get model, b.Binding)

0 commit comments

Comments
 (0)