这需要以不同的方式处理,因为EventHandler<T> 类型在这里不能按预期工作。 (至少不适合我)
首先,对于EventArgs,请记住这是一个类型,因此您不能在没有强制转换的情况下将它们分配给Status 属性(作为字符串)。这样做的方法是定义您自己的从 EventArgs 派生的参数类型,如下所示:
public class PatientEventArgs: EventArgs
{
public string PatientName {get; set;}
public string StatusValue {get; set;}
}
接下来对于您需要使用的处理程序方法,将其设置为异步方法。我发现异步很重要,因此您可以更远地使用InvokeAsync,并避免在线程和调度程序不同意时出现异常,例如在其他窗口打开或其他用户在其他地方登录时,通过这篇文章:
Discussion on thread vs. Synchronization Context
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.razor.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 方法,同时更好地为您管理依赖注入。
进一步阅读 HERE(请注意,我没有对此示例进行深入探讨,因为它使用的是单例,但值得一读以了解 Blazor 中的 DI 生命周期)
然后在你的 AppHeader.razor
....
@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>
这应该会根据需要多播您的事件,并且所有订阅者都应该选择并更新它。
Here is a quick working demo if needed,改编自我一直在研究的另一个版本。