如何从 Blazor 中的组件以单例形式更新 属性?
How to get updated property in singleton from a component in Blazor?
我刚刚更改了默认的 Blazor 示例来说明这个问题。
MainLayout.razor(这是页面的顶部,只是替换了关于显示计数器)
@inherits LayoutComponentBase
@inject TestClass testClass
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
Counter: @testClass.Counter
</div>
<div class="content px-4">
@Body
</div>
Counter.razor(这个被修改为使用局部变量,调用方法通过 class 递增并显示来自 class)
@page "/counter"
@inject TestClass testClass
<h1>Counter</h1>
<p>Current count:@testClass.Counter</p>
<button class="btn btn-primary" @onclick="(e => testClass.Increment())">Click me</button>
@code {
}
TestClass.cs(这个是class加上当前值和递增的方法)
正在使用系统;
使用 System.Collections.Generic;
使用 System.Linq;
使用 System.Threading.Tasks;
namespace TestBlazor.Classes
{
public class TestClass
{
public int Counter { get; set; } = 10;
public void Increment() {
Counter++;
}
}
}
这是按几次增量按钮后的结果:
因此,页面本身可以在每次更改时显示当前值,但是页面顶部的组件不能。它只是显示默认值 10。
这也是我的Program.cs
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using TestBlazor.Classes;
namespace TestBlazor
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddSingleton<TestClass>();
await builder.Build().RunAsync();
}
}
}
使用 Core5
您需要通知 MainLayout 组件其状态已更改,并且他应该重新呈现。这可以通过定义每当计数器变量递增时执行的事件委托来实现:
TestClass.cs
public class TestClass
{
public int Counter { get; set; } = 10;
public void Increment()
{
Counter++;
Notify?.Invoke();
}
public event Action Notify;
}
将此代码添加到 MainLayout 页面
@code{
protected override void OnInitialized()
{
testClass.Notify += () => InvokeAsync(StateHasChanged);
base.OnInitialized();
}
}
您还必须实施 IDisposable
我刚刚更改了默认的 Blazor 示例来说明这个问题。
MainLayout.razor(这是页面的顶部,只是替换了关于显示计数器)
@inherits LayoutComponentBase
@inject TestClass testClass
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
Counter: @testClass.Counter
</div>
<div class="content px-4">
@Body
</div>
Counter.razor(这个被修改为使用局部变量,调用方法通过 class 递增并显示来自 class)
@page "/counter"
@inject TestClass testClass
<h1>Counter</h1>
<p>Current count:@testClass.Counter</p>
<button class="btn btn-primary" @onclick="(e => testClass.Increment())">Click me</button>
@code {
}
TestClass.cs(这个是class加上当前值和递增的方法)
正在使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Threading.Tasks;
namespace TestBlazor.Classes
{
public class TestClass
{
public int Counter { get; set; } = 10;
public void Increment() {
Counter++;
}
}
}
这是按几次增量按钮后的结果:
因此,页面本身可以在每次更改时显示当前值,但是页面顶部的组件不能。它只是显示默认值 10。
这也是我的Program.cs
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using TestBlazor.Classes;
namespace TestBlazor
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddSingleton<TestClass>();
await builder.Build().RunAsync();
}
}
}
使用 Core5
您需要通知 MainLayout 组件其状态已更改,并且他应该重新呈现。这可以通过定义每当计数器变量递增时执行的事件委托来实现:
TestClass.cs
public class TestClass
{
public int Counter { get; set; } = 10;
public void Increment()
{
Counter++;
Notify?.Invoke();
}
public event Action Notify;
}
将此代码添加到 MainLayout 页面
@code{
protected override void OnInitialized()
{
testClass.Notify += () => InvokeAsync(StateHasChanged);
base.OnInitialized();
}
}
您还必须实施 IDisposable