Blazor WASM UI 更新不一致

Blazor WASM UI updates inconsistent

我的应用程序中有一个简单的登录功能。登录开始时,布尔值设置为 true 以激活加载动画,完成后设置为 false 以隐藏它。问题是 UI 对第二部分没有反应,但对第一部分有反应。

这是函数:

private async void AttemptLogin()
{
    //This updates
    LoginInProgress = true;
    try
    {
        var result = await _loginPageViewModel.Login(Username, Password, exception => { Console.WriteLine(exception.Message); }); //TODO add notifier
        if (result)
        {
            Console.WriteLine("success");

            _navigationManager.NavigateTo("./");
        }
        else
        {
            Console.WriteLine("Failure");
        }

    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }
    finally
    {
        //This does not update
        LoginInProgress = false;
    }
    Console.WriteLine("Login attempt finished");
}

我正在使用 blazorise 作为组件框架,这就是值的绑定方式(+ 一个额外的测试复选框,选中和取消选中会按预期更新所有内容):

<Button Clicked="AttemptLogin" @bind-Loading="LoginInProgress">Login</Button>
<Check TValue="bool" @bind-Checked="LoginInProgress">Test</Check>
     

目前,LoginInProgress = false; 处的 StateHasChanged 似乎有效,但我不喜欢我必须将它放在某些地方而不是其他地方。我做错了什么?

Blazor 将在组件中的任何事件处理程序完成后执行当前组件的内部“StateHasChanged”重新呈现。

因此,在正常情况下捕获“Clicked”事件并在“AttemptLogin”方法中处理它,然后 Blazor 引擎将在 AttemptLogin 完成后重新呈现并考虑变量“LoginInProgress = false”。无需手动调用“StateHasChanged.

但是,由于您的方法是异步的,因此引擎将等待完成。通常,您会 return 引擎将保留并等待该任务完成后再执行重新渲染的任务。

在你的例子中,你 return 是一个 void 而不是一个 Task。结果是,只要您的 AttempLogin 方法首先调用它 await,控制权就会 return 交给调用者(Blazor 引擎),它将认为该方法已完成。

var result = await _loginPageViewModel
    .Login(Username, Password, exception => 
     { Console.WriteLine(exception.Message); });

如果您 return 编辑了一个任务,它会等到方法完成(结果由任务提供),但是因为您 return 一个空的,那么引擎期望该方法没有进一步的响应并立即开始重新渲染。此重新渲染将在执行此行之前发生:

LoginInProgress = false;

因此,将在 LoginInProgress 仍然为真时应用重新呈现。

将您的 return 类型更改为任务,重新呈现将延迟到事件处理程序完成。