From 0b93c554a75a704b2b02e7dd93d441fd99e3994f Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Thu, 3 Jul 2025 22:13:23 +0100 Subject: [PATCH] Refactor ViewModel change subscriptions in Blazor components Consolidated and streamlined the logic for subscribing to ViewModel changes and property changes in ReactiveComponentBase, ReactiveInjectableComponentBase, and ReactiveLayoutComponentBase. This improves code readability and consistency across the components by using a shared pattern for handling ViewModel and property change notifications. --- .../ReactiveComponentBase.cs | 18 ++++---- .../ReactiveInjectableComponentBase.cs | 18 ++++---- .../ReactiveLayoutComponentBase.cs | 42 +++++++++++-------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/ReactiveUI.Blazor/ReactiveComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveComponentBase.cs index 82198d8494..eb892af085 100644 --- a/src/ReactiveUI.Blazor/ReactiveComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveComponentBase.cs @@ -97,15 +97,15 @@ protected override void OnAfterRender(bool firstRender) viewModelChanged .Select(x => - Observable - .FromEvent( - eventHandler => - { - void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); - return Handler; - }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) + Observable + .FromEvent( + eventHandler => + { + void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); + return Handler; + }, + eh => x.PropertyChanged += eh, + eh => x.PropertyChanged -= eh)) .Switch() .Subscribe(_ => InvokeAsync(StateHasChanged)) .DisposeWith(_compositeDisposable); diff --git a/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs index 6373061435..b97ab997de 100644 --- a/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs @@ -98,15 +98,15 @@ protected override void OnAfterRender(bool firstRender) viewModelChanged .Select(x => - Observable - .FromEvent( - eventHandler => - { - void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); - return Handler; - }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) + Observable + .FromEvent( + eventHandler => + { + void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); + return Handler; + }, + eh => x.PropertyChanged += eh, + eh => x.PropertyChanged -= eh)) .Switch() .Subscribe(_ => InvokeAsync(StateHasChanged)) .DisposeWith(_compositeDisposable); diff --git a/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs index 4c5e3d48b5..0fe81599bf 100644 --- a/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs @@ -84,34 +84,40 @@ protected override void OnAfterRender(bool isFirstRender) { if (isFirstRender) { - this.WhenAnyValue(x => x.ViewModel) - .Skip(1) - .WhereNotNull() + var viewModelChanged = + this.WhenAnyValue(x => x.ViewModel) + .WhereNotNull() + .Publish() + .RefCount(2); + + viewModelChanged + .Subscribe(_ => InvokeAsync(StateHasChanged)) + .DisposeWith(_compositeDisposable); + + viewModelChanged + .Select(x => + Observable + .FromEvent( + eventHandler => + { + void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); + return Handler; + }, + eh => x.PropertyChanged += eh, + eh => x.PropertyChanged -= eh)) + .Switch() .Subscribe(_ => InvokeAsync(StateHasChanged)) .DisposeWith(_compositeDisposable); } - this.WhenAnyValue(x => x.ViewModel) - .WhereNotNull() - .Select(x => Observable.FromEvent( - eventHandler => - { - void Handler(object? sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); - return Handler; - }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) - .Switch() - .Do(_ => InvokeAsync(StateHasChanged)) - .Subscribe() - .DisposeWith(_compositeDisposable); + base.OnAfterRender(isFirstRender); } /// /// Invokes the property changed event. /// /// The name of the property. - protected virtual void OnPropertyChanged([CallerMemberName]string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); /// /// Cleans up the managed resources of the object.