Skip to content

Commit 713e8f9

Browse files
committed
Get rid of Typed refs so that this can be mapped / boxed
1 parent 945d296 commit 713e8f9

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

src/Elmish.WPF/BindingVmHelpers.fs

Lines changed: 32 additions & 23 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, 'bindingViewModel> = {
108108
SubModelData: SubModelData<'model, 'msg, 'bindingModel, 'bindingMsg, 'bindingViewModel>
109-
Vm: 'bindingViewModel voption ref
109+
GetVm: unit -> 'bindingViewModel voption
110+
SetVm: 'bindingViewModel voption -> unit
110111
}
111112

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

119121
type SubModelSeqUnkeyedBinding<'model, 'msg, 'bindingModel, 'bindingMsg, 'bindingViewModel, 'vmCollection> = {
@@ -165,7 +167,8 @@ type BaseVmBinding<'model, 'msg, 'a> =
165167

166168
type CachedBinding<'model, 'msg, 'a> = {
167169
Binding: VmBinding<'model, 'msg, 'a>
168-
Cache: 'a option ref
170+
GetCache: unit -> 'a option
171+
SetCache: 'a option -> unit
169172
}
170173

171174
and ValidationBinding<'model, 'msg, 'a> = {
@@ -197,7 +200,7 @@ and VmBinding<'model, 'msg, 'a> =
197200

198201
with
199202

200-
member this.AddCaching = Cached { Binding = this; Cache = ref None }
203+
member this.AddCaching = let mutable cache = None in Cached { Binding = this; GetCache = (fun () -> cache); SetCache = fun c -> cache <- c }
201204
member this.AddValidation currentModel validate =
202205
{ Binding = this
203206
Validate = validate
@@ -317,18 +320,20 @@ type Initialize<'a>
317320
d.GetModel initialModel
318321
|> ValueOption.map (fun m -> ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs)
319322
|> ValueOption.map d.CreateViewModel
320-
|> (fun vm -> { SubModelData = d; Vm = ref vm })
323+
|> (fun vm -> let mutable vm = vm in { SubModelData = d; GetVm = (fun () -> vm); SetVm = fun nvm -> vm <- nvm })
321324
|> SubModel
322325
|> Some
323326
| SubModelWinData d ->
324327
let d = d |> BindingData.SubModelWin.measureFunctions measure measure measure2
325328
let toMsg = fun msg -> d.ToMsg (getCurrentModel ()) msg
326329
match d.GetState initialModel with
327330
| WindowState.Closed ->
331+
let mutable vmWinState = WindowState.Closed
328332
{ SubModelWinData = d
329333
WinRef = WeakReference<_>(null)
330334
PreventClose = ref true
331-
VmWinState = ref WindowState.Closed }
335+
GetVmWinState = fun () -> vmWinState
336+
SetVmWinState = fun vmState -> vmWinState <- vmState }
332337
| WindowState.Hidden m ->
333338
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
334339
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -337,10 +342,12 @@ type Initialize<'a>
337342
let preventClose = ref true
338343
log.LogTrace("[{BindingNameChain}] Creating hidden window", chain)
339344
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Hidden getCurrentModel dispatch
345+
let mutable vmWinState = WindowState.Hidden vm
340346
{ SubModelWinData = d
341347
WinRef = winRef
342348
PreventClose = preventClose
343-
VmWinState = ref <| WindowState.Hidden vm }
349+
GetVmWinState = fun () -> vmWinState
350+
SetVmWinState = fun vm -> vmWinState <- vm }
344351
| WindowState.Visible m ->
345352
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
346353
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
@@ -349,10 +356,12 @@ type Initialize<'a>
349356
let preventClose = ref true
350357
log.LogTrace("[{BindingNameChain}] Creating visible window", chain)
351358
Helpers2.showNewWindow winRef d.GetWindow d.IsModal d.OnCloseRequested preventClose vm Visibility.Visible getCurrentModel dispatch
359+
let mutable vmWinState = WindowState.Visible vm
352360
{ SubModelWinData = d
353361
WinRef = winRef
354362
PreventClose = preventClose
355-
VmWinState = ref <| WindowState.Visible vm }
363+
GetVmWinState = fun () -> vmWinState
364+
SetVmWinState = fun vm -> vmWinState <- vm }
356365
|> SubModelWin
357366
|> Some
358367
| SubModelSeqUnkeyedData d ->
@@ -462,16 +471,16 @@ type Update
462471
| Cmd cmd -> cmd |> CanExecuteChanged |> List.singleton
463472
| SubModel b ->
464473
let d = b.SubModelData
465-
match b.Vm.Value, d.GetModel newModel with
474+
match b.GetVm (), d.GetModel newModel with
466475
| ValueNone, ValueNone -> []
467476
| ValueSome _, ValueNone ->
468-
b.Vm.Value <- ValueNone
477+
b.SetVm ValueNone
469478
[ PropertyChanged name ]
470479
| ValueNone, ValueSome m ->
471480
let toMsg = fun msg -> d.ToMsg currentModel msg
472481
let chain = LoggingViewModelArgs.getNameChainFor nameChain name
473482
let args = ViewModelArgs.create m (toMsg >> dispatch) chain loggingArgs
474-
b.Vm.Value <- ValueSome <| d.CreateViewModel(args)
483+
b.SetVm (ValueSome <| d.CreateViewModel(args))
475484
[ PropertyChanged name ]
476485
| ValueSome vm, ValueSome m ->
477486
d.UpdateViewModel (vm, m)
@@ -522,7 +531,7 @@ type Update
522531
let args = ViewModelArgs.create model (toMsg >> dispatch) chain loggingArgs
523532
d.CreateViewModel args
524533

525-
match b.VmWinState.Value, d.GetState newModel with
534+
match b.GetVmWinState(), d.GetState newModel with
526535
| WindowState.Closed, WindowState.Closed ->
527536
[]
528537
| WindowState.Hidden vm, WindowState.Hidden m
@@ -532,29 +541,29 @@ type Update
532541
| WindowState.Hidden _, WindowState.Closed
533542
| WindowState.Visible _, WindowState.Closed ->
534543
close ()
535-
b.VmWinState.Value <- WindowState.Closed
544+
b.SetVmWinState WindowState.Closed
536545
[ PropertyChanged name ]
537546
| WindowState.Visible vm, WindowState.Hidden m ->
538547
hide ()
539548
d.UpdateViewModel (vm, m)
540-
b.VmWinState.Value <- WindowState.Hidden vm
549+
b.SetVmWinState (WindowState.Hidden vm)
541550
[]
542551
| WindowState.Hidden vm, WindowState.Visible m ->
543552
d.UpdateViewModel (vm, m)
544553
showHidden ()
545-
b.VmWinState.Value <- WindowState.Visible vm
554+
b.SetVmWinState (WindowState.Visible vm)
546555
[]
547556
| WindowState.Closed, WindowState.Hidden m ->
548557
let vm = newVm m
549558
log.LogTrace("[{BindingNameChain}] Creating hidden window", winPropChain)
550559
showNew vm Visibility.Hidden (fun () -> currentModel) dispatch
551-
b.VmWinState.Value <- WindowState.Hidden vm
560+
b.SetVmWinState (WindowState.Hidden vm)
552561
[ PropertyChanged name ]
553562
| WindowState.Closed, WindowState.Visible m ->
554563
let vm = newVm m
555564
log.LogTrace("[{BindingNameChain}] Creating visible window", winPropChain)
556565
showNew vm Visibility.Visible (fun () -> currentModel) dispatch
557-
b.VmWinState.Value <- WindowState.Visible vm
566+
b.SetVmWinState (WindowState.Visible vm)
558567
[ PropertyChanged name ]
559568
| SubModelSeqUnkeyed b ->
560569
let d = b.SubModelSeqUnkeyedData
@@ -598,7 +607,7 @@ type Update
598607
let updates = this.Recursive(currentModel, newModel, dispatch, b.Binding)
599608
updates
600609
|> List.filter UpdateData.isPropertyChanged
601-
|> List.iter (fun _ -> b.Cache.Value <- None)
610+
|> List.iter (fun _ -> b.SetCache None)
602611
updates
603612
| Validatation b ->
604613
let updates = this.Recursive(currentModel, newModel, dispatch, b.Binding)
@@ -628,9 +637,9 @@ type Get<'a>(nameChain: string) =
628637
| OneWayToSource _ -> GetError.OneWayToSource |> Error
629638
| OneWaySeq { Values = vals } -> vals.BoxedCollection() |> Ok
630639
| Cmd cmd -> cmd |> unbox |> Ok
631-
| SubModel { Vm = vm } -> vm.Value |> ValueOption.toNull |> Ok
632-
| SubModelWin { VmWinState = vm } ->
633-
vm.Value
640+
| SubModel { GetVm = getvm } -> getvm() |> ValueOption.toNull |> Ok
641+
| SubModelWin { GetVmWinState = getvm } ->
642+
getvm()
634643
|> WindowState.toVOption
635644
|> ValueOption.toNull
636645
|> Ok
@@ -658,11 +667,11 @@ type Get<'a>(nameChain: string) =
658667
match binding with
659668
| BaseVmBinding b -> this.Base(model, b)
660669
| Cached b ->
661-
match b.Cache.Value with
670+
match b.GetCache() with
662671
| Some v -> v |> Ok
663672
| None ->
664673
let x = this.Recursive(model, b.Binding)
665-
x |> Result.iter (fun v -> b.Cache.Value <- Some v)
674+
x |> Result.iter (fun v -> b.SetCache (Some v))
666675
x
667676
| Validatation b -> this.Recursive(model, b.Binding)
668677
| Lazy b -> this.Recursive(b.Get model, b.Binding)

0 commit comments

Comments
 (0)