多个窗口中的 Web 事件处理 (Blazor)

Web event handling in multiple windows (Blazor)

提问人:beginner 提问时间:5/4/2023 最后编辑:beginner 更新时间:5/9/2023 访问量:207

问:

我刚刚开始上网,这次我在事件处理方面遇到了麻烦。我使用 blazor 进行开发,但这似乎是一个普遍适用的问题。

我被困的地方是这个。我想在收到消息时通知页面。当我有一个浏览器屏幕时,我没有遇到任何问题,但是当我在打开两个屏幕的情况下测试我的网络时,事件无法正常工作。如何解决此问题?

下面是我的代码。

ServiceInfoReceiveHandler.cs
public event EventHandler<(string contentType, string serverName, string message)> InstallServiceInfoReceived;
...
public void Receive(BasicDeliverEventArgs eventArgs)
{
  if (contentType == "SVCMGMT/INSTALL/SVCINFO")
  {
    InstallServiceInfoReceived?.Invoke(this, (contentType, serverName, message));
    ...
  }
}

我像这样触发事件,每当有消息传入时,总是调用接收函数。这不是消息没有到达的问题。

page.razor

@inject ServiceInfoReceiveHandler _serviceInfoReceiveHandler

protected override async Task OnInitializedAsync()
{ 
  _serviceInfoReceiveHandler.InstallServiceInfoReceived += OnServiceInfoReceived;
}
private async void OnServiceInfoReceived(object sender, (string contentType, string serverName, string message) e)
{
...
}

我想要结果的剃刀页面如上所示,但未调用 OnInfoReceived。

.NET Web 事件处理 Blazor

评论

0赞 MrC aka Shaun Curtis 5/4/2023
WASM 还是服务器?
0赞 beginner 5/4/2023
@MrCakaShaunCurtis 这是 blazor 服务器
0赞 clamchoda 5/5/2023
我这里有一个答案,解释了如何使用服务做到这一点;stackoverflow.com/a/75891945/591285

答:

1赞 MrC aka Shaun Curtis 5/4/2023 #1

下面是用于在页面与事件之间进行通信的 Blazor 通知模式的简单演示。

首先是通知服务。

namespace SO76170542.Data;

public class HelloService
{
    public event EventHandler<HelloEventArgs>? HelloChanged;

    private string? _hello;

    public string HelloMessage => _hello ?? "No Message Set";

    public void NotifyHelloChanged(string? hello)
    {
        _hello = hello;
        this.HelloChanged?.Invoke(this, new(hello));
    }
}

public class HelloEventArgs : EventArgs
{
    public string? Hello { get; set; }

    public HelloEventArgs(string? hello)
        => Hello = hello;
}

已注册 程序。

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<HelloService>();

var app = builder.Build();

以及用于生成和使用消息的页面。

@page "/"
@inject HelloService helloService

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<div class="m-2">
    <button class="btn btn-dark" @onclick=this.UpdateHello>Update Hello</button>
</div>

<div class="alert alert-primary">@helloService.HelloMessage</div>

@code {

    // Register the event handler
    protected override void OnInitialized()
        => this.helloService.HelloChanged += this.OnHelloChanged;

    private Task UpdateHello()
    {
        helloService.NotifyHelloChanged($"Hello Blazor at {DateTime.Now.ToLongTimeString()}");
        return Task.CompletedTask;
    }

    public void OnHelloChanged(object? sender, HelloEventArgs e)
        => InvokeAsync(this.StateHasChanged);

    // We must de-register the even handler
    public void Dispose()
        => this.helloService.HelloChanged -= this.OnHelloChanged;
}

您可以在此处看到相同的模式:如何触发/刷新我的主 .RAZOR 页面,该主 .API 调用完成时的 RAZOR 页面?FetchData

enter image description here

评论

0赞 beginner 5/5/2023
感谢您的友好回复。我还没有在我现有的代码上尝试过,但根据您的示例,您似乎将 HelloService 设置为单例,这与我的不同。我将其设置为作用域,但是否必须将其设置为单例?
0赞 MrC aka Shaun Curtis 5/5/2023
如果将其设置为作用域,则实例将仅存在于 Hub SPA 会话的作用域内。在我上面的图片中,您将有 4 个实例,每个会话一个,我认为这是您正在观察到的,但不想要,
0赞 beginner 5/8/2023
我仍然需要测试更多,但更改为单例似乎已经解决了这个问题。但是,即使我将您发布的示例更改为 scoped,按下按钮的窗口中的值也会发生变化,这是我想要的结果。有没有可能我遇到麻烦的原因是因为我没有直接通过按钮调用事件,而是在加载页面时通过消息代理调用事件,当响应到来时,它会在触发事件的过程中流向另一个对象(另一个窗口)?
0赞 MrC aka Shaun Curtis 5/8/2023
你只想在一个屏幕中接收讯息吗?消息从何而来?
0赞 beginner 5/9/2023
我的消息是通过客户端的 RabbitMQ 传递的。我不一定需要在一个屏幕上接收它,我认为像你那样将它实现为单例会起作用,但我不熟悉单例,所以我只是想知道是否存在我不知道的问题。所以我想知道为什么在您的示例中,当它被限定时,当我按下按钮时,我在该屏幕上获得该事件,但在上面的旧代码中,我在随机屏幕上获得它。