Skip to content

Commit 8729191

Browse files
authored
Fix Blazor ViewModelActivation (#3871)
<!-- Please be sure to read the [Contribute](https://github.com/reactiveui/reactiveui#contribute) section of the README --> **What kind of change does this PR introduce?** <!-- Bug fix, feature, docs update, ... --> Bug fix. Current implementation did increase RefCount under ViewModelActivator once, but decrement it twice on deactivation. So the ViewModel was bricked if it was used as Scoped, or Singleton and would never activate again. **What is the current behavior?** <!-- You can also link to an open issue here. --> Fixed behavior **What is the new behavior?** <!-- If this is a feature change --> **What might this PR break?** Should only fix **Please check if the PR fulfills these requirements** - [ ] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) **Other information**:
1 parent bf5e1c6 commit 8729191

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

src/ReactiveUI.Blazor/ReactiveComponentBase.cs

+6
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ public void Dispose()
6969
/// <inheritdoc />
7070
protected override void OnInitialized()
7171
{
72+
if (ViewModel is IActivatableViewModel avm)
73+
{
74+
Activated.Subscribe(_ => avm.Activator.Activate()).DisposeWith(_compositeDisposable);
75+
Deactivated.Subscribe(_ => avm.Activator.Deactivate());
76+
}
77+
7278
_initSubject.OnNext(Unit.Default);
7379
base.OnInitialized();
7480
}

src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,14 @@ public void Dispose()
6969
/// <inheritdoc />
7070
protected override void OnInitialized()
7171
{
72-
_initSubject.OnNext(Unit.Default);
7372
if (ViewModel is IActivatableViewModel avm)
7473
{
7574
Activated.Subscribe(_ => avm.Activator.Activate()).DisposeWith(_compositeDisposable);
7675
Deactivated.Subscribe(_ => avm.Activator.Deactivate());
7776
}
7877

78+
_initSubject.OnNext(Unit.Default);
79+
7980
base.OnInitialized();
8081
}
8182

src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs

+16-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public class ReactiveLayoutComponentBase<T> : LayoutComponentBase, IViewFor<T>,
1616
where T : class, INotifyPropertyChanged
1717
{
1818
private readonly Subject<Unit> _initSubject = new();
19+
[SuppressMessage("Design", "CA2213: Dispose object", Justification = "Used for deactivation.")]
20+
private readonly Subject<Unit> _deactivateSubject = new();
21+
private readonly CompositeDisposable _compositeDisposable = [];
1922

2023
private T? _viewModel;
2124

@@ -51,7 +54,7 @@ public T? ViewModel
5154
public IObservable<Unit> Activated => _initSubject.AsObservable();
5255

5356
/// <inheritdoc />
54-
public IObservable<Unit> Deactivated => Observable.Empty<Unit>();
57+
public IObservable<Unit> Deactivated => _deactivateSubject.AsObservable();
5558

5659
/// <inheritdoc />
5760
public void Dispose()
@@ -64,6 +67,12 @@ public void Dispose()
6467
/// <inheritdoc />
6568
protected override void OnInitialized()
6669
{
70+
if (ViewModel is IActivatableViewModel avm)
71+
{
72+
Activated.Subscribe(_ => avm.Activator.Activate()).DisposeWith(_compositeDisposable);
73+
Deactivated.Subscribe(_ => avm.Activator.Deactivate());
74+
}
75+
6776
_initSubject.OnNext(Unit.Default);
6877
base.OnInitialized();
6978
}
@@ -78,7 +87,8 @@ protected override void OnAfterRender(bool isFirstRender)
7887
this.WhenAnyValue(x => x.ViewModel)
7988
.Skip(1)
8089
.WhereNotNull()
81-
.Subscribe(_ => InvokeAsync(StateHasChanged));
90+
.Subscribe(_ => InvokeAsync(StateHasChanged))
91+
.DisposeWith(_compositeDisposable);
8292
}
8393

8494
this.WhenAnyValue(x => x.ViewModel)
@@ -93,7 +103,8 @@ protected override void OnAfterRender(bool isFirstRender)
93103
eh => x.PropertyChanged -= eh))
94104
.Switch()
95105
.Do(_ => InvokeAsync(StateHasChanged))
96-
.Subscribe();
106+
.Subscribe()
107+
.DisposeWith(_compositeDisposable);
97108
}
98109

99110
/// <summary>
@@ -113,6 +124,8 @@ protected virtual void Dispose(bool disposing)
113124
if (disposing)
114125
{
115126
_initSubject.Dispose();
127+
_compositeDisposable.Dispose();
128+
_deactivateSubject.OnNext(Unit.Default);
116129
}
117130

118131
_disposedValue = true;

0 commit comments

Comments
 (0)