Blazor:更改绑定属性不会更新视图

时间:2019-12-16 09:52:39

标签: blazor blazor-server-side

我在Blazor(服务器端)具有一个InputForm控件的EditForm。表单绑定到模型类,而InputText字段绑定到由本地存储支持的单个属性。

页面加载时,InputText显示空白值。我调用了一个InitAsync方法来异步地从本地存储中加载数据。可以,但是用加载的数据设置属性不会更新视图。

如果我使用单向绑定而不是InputText(具有双向绑定)将值绑定到span标记,则会发生相同的问题。

从存储异步加载数据后如何更新视图?

视图/组件类:

@inject Blazored.LocalStorage.ILocalStorageService localStorage
<EditForm Model="@model" class="pl-4 pr-3 py-1 loginform" OnValidSubmit="@HandleValidSubmit">
    <span>model.OperID</span>    
    <InputText class="form-control mr-sm-2" style="width: 158px" placeholder="OperID"  @bind-Value="@model.OperID"></InputText>
    <button class="btn btn-success oi oi-account-login" @onclick="Login"></button>
</EditForm>


@code {   
    private Models.MainModel model = new Models.MainModel();


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {       
        await model.InitializeAsync(localStorage);
    }


    void Login()
    {

    }


    private void HandleValidSubmit()
    {
        Console.WriteLine("OnValidSubmit");
    }
}

模型类:

public class MainModel
{
    Blazored.LocalStorage.ILocalStorageService? localStorage;

    public MainModel()
    {

    }


    public async Task InitializeAsync(Blazored.LocalStorage.ILocalStorageService localStorage)
    {
        this.localStorage = localStorage;

        if (localStorage != null)
        {
            // the value loads correctly, but setting the property does not cause the view to update as it should. 
            // ConfigureAwait(false) makes no difference...
            OperID = await localStorage.GetItemAsync<string?>("OperID").ConfigureAwait(false); 
        }
    }



    string? operID = "DUMMY"; // null;
    public string? OperID
    {
        get 
        {
            return operID;
        }

        set
        {
            operID = value;

            if (localStorage != null)
            {
                localStorage.SetItemAsync("OperID", value);
            }
        }

    }
}

2 个答案:

答案 0 :(得分:0)

由于您正在使用服务器端Blazor,并且可能已启用了预渲染设置,因此您不能也不应使用OnIntialized或OnInitializedAsync方法。相反,您应该使用OnAfterRenderAsync方法,该方法是使用JSInterop的适当位置。并且您应该将代码包含在if语句中,以检查这是否是第一个渲染,如下所示:

protected override async Task OnAfterRenderAsync(bool firstRender)
    {    if( firstRender)
         {   
             await model.InitializeAsync(localStorage);
             // And of course the StateHasChanged method should be called here to refresh the page.
             StateHasChanged(); 
          }
    }

这样,您的模型仅初始化一次,而不是在每次执行OnAfterRenderAsync时(每次需要重新呈现页面组件时)都进行初始化。

注意:如果要重新渲染,则根本不会调用OnAfterRenderAsync方法。

_Host.cshtml中的以下代码片段可以告诉您是否正在使用预渲染:

<app>
     <component type="typeof(App)" render-mode="ServerPrerendered" />   
</app>

从设置中可以看到,您的应用已在服务器上预呈现。 Blazored.LocalStorage是否支持数据保护(如果不支持)。使用Blazor团队创建的库。

答案 1 :(得分:0)

这是我为了使其工作而更改的代码:

protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) // prevent infinite loop
        {         
            await model.InitializeAsync(localStorage); // load data

            StateHasChanged();  // update view

        }
    }