更新其他组件中的组件元素

时间:2020-06-02 22:16:55

标签: blazor

我正在尝试从页面更改我的组件之一内的元素的类,但是类从未改变。我在函数中放入了Console.Writeline,该函数正在运行definitley。

CircleClass变量默认设置为"danger",并且可以正常工作,div以danger class开始。 console.writeline确认变量已被更改,只是不更新​​元素。

组件中的代码

<div class="circle @CircleClass"></div>

@code {
    private string CircleClass = "danger";

    public void ChangeStatus(int status)
    {
        switch (status)
        {
            case 0:
                CircleClass = "idle";
                break;
            case 1:
                CircleClass = "safety";
                break;
            case 2:
                CircleClass = "danger";
                break;
        }

        Console.WriteLine($"{status} Circle: {CircleClass}");
    }
}

第一次尝试

@page "/"

@Inject Nav nav

<button @onclick="@(e => nav.ChangeStatus(2))">Two</button>

Startup.cs中,我添加了此内容:

services.AddSingleton<Nav>();

第二次尝试

@page "/"

<button @onclick="@(e => ChangeStatus(2))">Two</button>

private void ChangeStatus(int status)
{
    Nav nav = new Nav();
    nav.ChangeStatus(status);
}

我认为它可能与创建类的新实例有关,该实例无法更改我需要更改的元素的类,尽管我认为应该在使用AddSingleton时解决

有人知道是什么原因引起的吗?


在组件内部调用该函数可确认该函数确实有效。

组件:

protected override void OnInitialized()
{
    ChangeStatus(1);
}

我正在尝试:

Nav.razor

<li id="status">
    <div class="circle @CircleClass"></div>
</li>

@code {
    private string CircleClass = "danger";

    public void ChangeStatus(int status)
    {
        switch (status)
        {
            case 0:
                CircleClass = "idle";
                break;
            case 1:
                CircleClass = "safety";
                break;
            case 2:
                CircleClass = "danger";
                break;
            default:
                CircleClass = "idle";
                break;
        }

        Console.WriteLine($"{status} Circle: {CircleClass}");

        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();

    services.AddSingleton<Nav>();
}

Index.razor

@page "/"

@inject Nav nav 

<button @onclick="@(e => nav.ChangeStatus(0))">Zero</button>
<button @onclick="@(e => nav.ChangeStatus(1))">One</button>
<button @onclick="@(e => nav.ChangeStatus(2))">Two</button>

在上面的代码示例中,我使用按钮尝试从页面上运行nav组件中的功能,但最终,我将从不同的地方运行这些功能,而这些地方将不会在没有直接用户输入的情况下成为页面。


Nav组件是在我的MainLayout中定义/创建的,它没有直接应用于Index页面。

2 个答案:

答案 0 :(得分:1)

您可以执行以下操作。我认为您不需要导航服务。您可以从页面本身调用和更改类的值。

内部索引页面

HTML

<Nav @ref="navComp"></Nav>

<button @onclick="@(e => navComp.ChangeStatus(0))">Zero</button>
<button @onclick="@(e => navComp.ChangeStatus(1))">One</button>
<button @onclick="@(e => navComp.ChangeStatus(2))">Two</button>

C#代码

@code {
Nav navComp;

    //other code
}

内部导航组件

HTML

<h3>Nav</h3>
<li id="status">
    <div class="circle @CircleClass"></div>
</li>

C#代码

@code {
    private string CircleClass = "danger";

    public void ChangeStatus(int status)
    {
        switch (status)
        {
            case 0:
                CircleClass = "idle";
                break;
            case 1:
                CircleClass = "safety";
                break;
            case 2:
                CircleClass = "danger";
                break;
            default:
                CircleClass = "idle";
                break;
        }

        Console.WriteLine($"{status} Circle: {CircleClass}");

        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }
}

您可以在此处看到输出。

output

答案 1 :(得分:1)

您需要提供可以帮助管理组件的服务。

首先:

  • 提供服务并向其移动更新组件的功能(在本例中为 members: "mongodb1:27017,mongodb2:27017,mongodb3:27017" )。
  • 将事件添加到新服务中,并在ChangeStatus()函数结束时触发它。

services / MyService.cs

ChangeStatus()

其次:

  • 在blazor应用程序中将服务添加为using System; namespace MyAppName.Services { public delegate void MyEventHandler(); public class MyService { public event MyEventHandler MyEvent; public string CircleClass = "danger"; public void ChangeStatus(int status) { switch (status) { case 0: CircleClass = "idle"; break; case 1: CircleClass = "safety"; break; case 2: CircleClass = "danger"; break; } // Fire event MyEvent?.Invoke(); } } }
  • 为便于访问,请将“服务”命名空间添加到您的Singleton文件中。

添加服务

_Imports.razor

将服务添加到_Imports.razor

// In Blazor Server-Side
// open Startup.cs and add:

public void ConfigureServices(IServiceCollection services)
{
    // [..]

    services.AddSingleton<MyService>();
}

// In Blazor WebAssembly
// open Program.cs and add:

public static async Task Main(string[] args)
{
    // [..]

    builder.Services.AddSingleton<MyService>();
}

第三次:

  • 将服务注入您的组件中。
  • 订阅组件中的事件,并创建一个函数,以在事件触发时运行// This will only work if the namespace // for your service is the MyAppName.Services. // If you put your service in the Services folder // you should be fine unless you renamed the namespace. @using MyAppName.Services

Component.razor

StateHasChanges()

最后:

  • 从其他地方(在本例中为页面)在服务中运行// At the top: @inject MyService myService // Subscribe to event and create function @code { protected override void OnInitialized() { myService.MyEvent+= UpdateState; } private void UpdateState() { // Need to use InvokeAsync, atleast // on Blazor Server-Side InvokeAsync(() => { StateHasChanged(); }); } } 功能

Index.razor

ChangeStatus()