【问题标题】:How to get updated property in singleton from a component in Blazor?如何从 Blazor 中的组件获取更新的单例属性?
【发布时间】:2021-05-27 20:37:54
【问题描述】:

我刚刚更改了默认的 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(这个被修改为使用局部变量,调用方法通过类递增并显示来自类的值)

@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(这个是当前值和递增方法的类)

使用系统; 使用 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

【问题讨论】:

    标签: blazor blazor-client-side


    【解决方案1】:

    您需要通知 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

    【讨论】:

    • 我们不能只使用绑定,因为 TestClass 是单例吗?
    • 它与服务的范围无关,而且这是一种单向绑定,从一个服务到一个组件,但是你需要通知MainLaout她应该重新渲染。在其他示例中,您可以创建双向绑定,或者可以在 TestClass 中定义一个事件,该事件具有可以传递给订阅者的数据。
    • @yasseros,看到这个:stackoverflow.com/a/62042629/6152891
    • 谢谢!是的,它成功了。我在其他地方阅读了这个解决方案,但我认为它可以有更直接的方法。还是谢谢!
    猜你喜欢
    • 2021-12-11
    • 2022-10-13
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    相关资源
    最近更新 更多