叫这个吧.EventHandler中的StateHasChanged



我有以下问题。我创建了一个事件并订阅了它,现在我希望UI在事件触发时发生更改。

using System;
using MintWebApp.Data;
using MintWebApp.Models;
using Microsoft.AspNetCore.Components;
namespace WebApp.UI.Core
{
public partial class AppHeader
{
public string status { get; set; }
[Inject]
public StateService state { get; set; }
EventHandler<string> onStatusChanged= (sender, eventArgs) => {
//Here i get the error, I can't access this and status
status = eventArgs;
this.StateHasChanged();
Console.WriteLine(eventArgs.PatientName);
};
protected override void OnInitialized() => state.StatusHandler += onStatusChanged;
}
}

我收到这个错误字段初始值设定项不能引用非静态字段、方法或属性"AppHeader.ppatientContext">

关键字"this"在当前上下文中不可用

如何订阅事件并更新UI

这需要以不同的方式处理,因为EventHandler<T>类型在这里不能按预期工作。(至少对我来说不是(

首先,对于EventArgs,请记住这是一个类型,因此不能在没有强制转换的情况下将它们分配给Status属性(作为字符串(。这样做的方法是定义自己的参数类型,该类型派生自EventArgs,类似于以下内容:

public class PatientEventArgs: EventArgs
{
public string PatientName {get; set;}
public string StatusValue {get; set;}
}

接下来,对于需要使用的处理程序方法,将其设置为异步方法。我发现异步很重要,所以当线程和调度程序不一致时,可以使用InvokeAsync,避免出现异常,就像在其他打开的窗口或其他在其他地方登录的用户中一样线程与同步上下文的讨论

private async void OnStatusChanged(object sender, EventArgs e) {

// Make sure the args are the type you are expecting        
if(e.GetType() == typeof(PatientEventArgs))
//Cast to the correct Args type to access properties
var patientStatus = e as PatientEvendArgs;
status = patientStatus.StatusValue;
Console.Writeline(patientStatus.PatientName);
/* Use InvokeAsync method with await to make sure 
StateHasChanged runs correctly here without interfering with another
thread (open window or other users) */
await InvokeAsync(() => StateHasChanged());
}

接下来,对于您的场景来说非常重要,您将使用Partial Class声明碰壁,因为您需要实现IDisposable,以便在组件拆卸时自行清理。相反,使用如下继承结构,并使用OnInitialized和Dispose重写

AppHeader.rarr.cs

public class AppHeaderBase : OwningComponentBase
{
// OnStatusChanged method as described above
protected override void OnInitialized() //Can use the Async version as well
{
// Unsubscribe once to make sure you are only connected once
// Prevents event propogation
// If this component is not subscribed this doesn't do anything
state.StatusHandler -= onStatusChanged;
// Subscribe to the event
state.StatusHandler += onStatusChanged;
}
protected override void Dispose(bool disposing)
{
// Unsubscribe on teardown, prevent event propogation and memory leaks
state.StatusHandler -= onStatusChanged;
} 
}

这利用了OwningComponentBase中的一些内置Blazor功能,并包括Dispose方法,同时为您更好地管理依赖注入。

进一步阅读这里(注意,我没有对这个例子深入研究,因为它使用的是单例,但值得一读以了解Blazor中的DI寿命(

然后在AppHeader.rarzor

....
@inherits AppHeaderBase
....

现在,当您从其他地方使用StateService中的事件处理程序时,使用需要传递的值构建一个新的PatientEventArgs类型:

var newArgs = new PatientEventArgs(){
PatientName = "SomeName",
StatusValue = "SomeStatus"  
};

并根据需要在代码中传递:

state.OnStatusChanged(this, newArgs);  

或者直接从Razor语法:

<button @onclick="@(() => state.OnStatusChanged(this, new PatientEventArgs(){ PatientName = "SomeName", StatusValue = "SomeStatus"})">Sender Button</button>

这应该根据需要多播您的事件,所有订阅者都应该接收并更新它。

如果需要的话,这里有一个快速工作的演示,改编自我一直在做的另一个版本

相关内容

  • 没有找到相关文章

最新更新