From aad14eb370857064701cee77305bf56e72e665e2 Mon Sep 17 00:00:00 2001 From: Yuriy Durov Date: Sun, 5 May 2024 13:17:02 +0400 Subject: [PATCH] State improvements --- .../Pages/CounterPage.razor | 11 ++++------- .../ViewModels/CounterPageViewModel.cs | 15 ++++++++++++++- .../AddRenderingEnvironmentExtension.cs | 2 +- .../Interfaces/IStateComponent.cs | 6 ++++++ .../Models/ComponentViewModel.cs | 8 +++++--- src/BitzArt.Blazor.MVVM/Models/PageBase.cs | 11 ++++++----- .../Models/RenderingEnvironment.cs | 11 +++++++++++ 7 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 src/BitzArt.Blazor.MVVM/Interfaces/IStateComponent.cs diff --git a/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/Pages/CounterPage.razor b/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/Pages/CounterPage.razor index eba1212..6080969 100644 --- a/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/Pages/CounterPage.razor +++ b/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/Pages/CounterPage.razor @@ -6,16 +6,13 @@

Counter

-

This page is currently being rendered using: @(OperatingSystem.IsBrowser() ? "WASM" : "Server")

+

Current render mode: @RenderingEnvironment

-@if (ViewModel.State is not null) -{ -

@ViewModel.State.Text

+

@ViewModel.State?.Text

-

Current count: @ViewModel.State.Count

+

Current count: @ViewModel.State?.Count

- -} + @{ base.BuildRenderTree(__builder); diff --git a/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/ViewModels/CounterPageViewModel.cs b/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/ViewModels/CounterPageViewModel.cs index 670f808..1fcc566 100644 --- a/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/ViewModels/CounterPageViewModel.cs +++ b/sample/BitzArt.Blazor.MVVM.SampleApp/BitzArt.Blazor.MVVM.SampleApp.Client/ViewModels/CounterPageViewModel.cs @@ -2,10 +2,23 @@ public class CounterPageViewModel : ComponentViewModel { + private readonly Timer _timer; + + public CounterPageViewModel() + { + _timer = new Timer(TimerIncrementCount, null, 1000, 1000); + } + + private void TimerIncrementCount(object? state) + { + State.Count++; + StateHasChanged(); + } + public override void InitializeState() { State.Count = 0; - State.Text = "ViewModel State initialized on: " + (OperatingSystem.IsBrowser() ? "Client" : "Server"); + State.Text = $"ViewModel State initialized on: {RenderingEnvironment}"; } public void IncrementCount() diff --git a/src/BitzArt.Blazor.MVVM/Extensions/AddRenderingEnvironmentExtension.cs b/src/BitzArt.Blazor.MVVM/Extensions/AddRenderingEnvironmentExtension.cs index 4c818bb..992bc19 100644 --- a/src/BitzArt.Blazor.MVVM/Extensions/AddRenderingEnvironmentExtension.cs +++ b/src/BitzArt.Blazor.MVVM/Extensions/AddRenderingEnvironmentExtension.cs @@ -7,7 +7,7 @@ public static class AddRenderingEnvironmentExtension { public static IServiceCollection AddRenderingEnvironment(this IServiceCollection services) { - services.AddTransient(x => x.GetRenderingEnvironment()); + services.AddScoped(x => x.GetRenderingEnvironment()); return services; } diff --git a/src/BitzArt.Blazor.MVVM/Interfaces/IStateComponent.cs b/src/BitzArt.Blazor.MVVM/Interfaces/IStateComponent.cs new file mode 100644 index 0000000..e436d12 --- /dev/null +++ b/src/BitzArt.Blazor.MVVM/Interfaces/IStateComponent.cs @@ -0,0 +1,6 @@ +namespace BitzArt.Blazor.MVVM; + +internal interface IStateComponent +{ + public void StateHasChanged(); +} \ No newline at end of file diff --git a/src/BitzArt.Blazor.MVVM/Models/ComponentViewModel.cs b/src/BitzArt.Blazor.MVVM/Models/ComponentViewModel.cs index 8dda8d0..465d021 100644 --- a/src/BitzArt.Blazor.MVVM/Models/ComponentViewModel.cs +++ b/src/BitzArt.Blazor.MVVM/Models/ComponentViewModel.cs @@ -5,15 +5,16 @@ /// public abstract class ComponentViewModel { - public delegate void StateChangedEventHandler(); - public event StateChangedEventHandler? StateChanged; + internal IStateComponent Component { get; set; } = null!; + + protected internal RenderingEnvironment RenderingEnvironment { get; internal set; } = null!; /// /// Notifies the component that the state has changed. /// protected void StateHasChanged() { - StateChanged?.Invoke(); + Component.StateHasChanged(); } } @@ -24,6 +25,7 @@ protected void StateHasChanged() public abstract class ComponentViewModel : ComponentViewModel, IStatefulViewModel where TState : class, new() { + /// /// Persistent state of this view model. /// diff --git a/src/BitzArt.Blazor.MVVM/Models/PageBase.cs b/src/BitzArt.Blazor.MVVM/Models/PageBase.cs index 8df5dd9..1542fd2 100644 --- a/src/BitzArt.Blazor.MVVM/Models/PageBase.cs +++ b/src/BitzArt.Blazor.MVVM/Models/PageBase.cs @@ -10,7 +10,7 @@ namespace BitzArt.Blazor.MVVM; /// Blazor page base class with view model support. /// /// Type of this component's ViewModel -public abstract partial class PageBase : ComponentBase +public abstract partial class PageBase : ComponentBase, IStateComponent where TViewModel : ComponentViewModel { private const string StateKey = "state"; @@ -25,7 +25,7 @@ public abstract partial class PageBase : ComponentBase private IJSRuntime Js { get; set; } = default!; [Inject] - private RenderingEnvironment RenderingEnvironment { get; set; } = null!; + protected RenderingEnvironment RenderingEnvironment { get; set; } = null!; /// /// Navigation manager. @@ -48,10 +48,9 @@ protected override void BuildRenderTree(RenderTreeBuilder builder) /// A representing any asynchronous operation. protected override async Task OnInitializedAsync() { - ViewModel.StateChanged += StateHasChanged; - await base.OnInitializedAsync(); - + ViewModel.Component = this; + ViewModel.RenderingEnvironment = RenderingEnvironment; await RestoreStateAsync(); } @@ -119,6 +118,8 @@ public override Task SetParametersAsync(ParameterView parameters) return base.SetParametersAsync(parameters); } + + void IStateComponent.StateHasChanged() => InvokeAsync(StateHasChanged); } internal static class StateJsonOptionsProvider diff --git a/src/BitzArt.Blazor.MVVM/Models/RenderingEnvironment.cs b/src/BitzArt.Blazor.MVVM/Models/RenderingEnvironment.cs index 17a8d6b..1ae1973 100644 --- a/src/BitzArt.Blazor.MVVM/Models/RenderingEnvironment.cs +++ b/src/BitzArt.Blazor.MVVM/Models/RenderingEnvironment.cs @@ -5,4 +5,15 @@ public class RenderingEnvironment public required bool IsPrerender { get; init; } public required bool IsServer { get; init; } public required bool IsClient { get; init; } + + public override string ToString() + { + if (IsClient) return "Client"; + if (IsServer) + { + if (IsPrerender) return "Server (prerender)"; + return "Server"; + } + return "Unknown"; + } }