System.InvalidOperationException:“渲染句柄尚未分配。”在 Blazor 服务器中

问题描述 投票:0回答:1

我创建了一个简单的 Blazor 应用程序,我需要在 index.razor 页面上显示加载屏幕。我不需要将其包含在 index.razor 页面上。我正在使用一些间接的方式来做到这一点。

首先,我创建了一个名为 Appsettings.cs 的类,并将加载逻辑带入其中

应用程序设置.cs

public class AppSettings
    {
        public static bool _IsProcessing { get; set; } = false;

        public static MainLayout _layout { get; set; } = new MainLayout();

        public static void Loading(bool isProcessing)
        {
            _IsProcessing = isProcessing;

            if(_layout !=null)
               _layout .LoadingScreenShowing(_IsProcessing);
        }

    }

然后我的index.razor文件是这样的,当按下下面的加载按钮时,我需要显示加载屏幕。

index.razor

<button onclick="PageLoading">Load</button>
@code{
  protected override void Oninitialized(){}

  private void PageLoading(){
     AppSettings.Loading(true);
     this.StateHasChanged();
     //do something
     AppSettings.Loading(false);
     this.StateHasChanged();
         
  }

在我将加载部分包含到 MainLayout.razor 中后,未明确加载到 index.razor 中。

MainLayout.razor

@inherits LayoutComponentBase

<PageTitle>BlazorApp1</PageTitle>

<div class="page">
<div class="sidebar">
    <NavMenu />
</div>

    <main>
        <div class="top-row px-4">
            <a href="https://learn.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            <Loading IsVisible="@IsLoading" @ref="load"/>  //loading component 
            @Body
        </article>
    </main>
</div>

我创建了一个分部类来放置主布局的功能部分。

MainLayout.razor.cs

public partial class MainLayout{
        private bool IsLoading;
        Loading load ;

        public async void LoadingScreenShowing(bool isLoading)
        {
            load = new Loading();
            IsLoading = isLoading;
            this.StateHasChanged();//exception is throwing from this line 
            await Task.CompletedTask;
        }
}

当执行 this.StateHasChanged() 行时,我收到称为的异常

System.InvalidOperationException:'渲染句柄尚未 已分配。'

为什么会出现这种情况?

c# razor blazor
1个回答
2
投票

你不能按照你想要的方式去做。 组件生命周期由渲染器管理:您无法创建组件实例并以某种方式将其硬塞到页面中。 这就是错误的原因。

这是您的代码的经过大量重构的版本,我认为它符合您的意图。

维护应用程序状态的范围服务(您的

AppSettings
):

public class AppStateService
{
    private bool _isLoaded;

    public event Action? LoadStateChanged;

    public bool IsLoaded
    {
        get => _isLoaded;
        set
        {
            if (_isLoaded != value)
            {
                _isLoaded = value;
                LoadStateChanged?.Invoke();
            }
        }
    }
}

在程序中注册:

builder.Services.AddScoped<AppStateService>();

加载组件 - 我使用了一个简单的引导警报来显示加载消息。

@inject AppStateService appStateService
@implements IDisposable

@if (!this.appStateService.IsLoaded)
{
    <div class="alert alert-danger">
        Page Loading...
    </div>
}

@code {
    protected override void OnInitialized()
        => this.appStateService.LoadStateChanged += this.OnStateChanged;

    private void OnStateChanged()
        => this.InvokeAsync(StateHasChanged);

    public void Dispose()
        => this.appStateService.LoadStateChanged -= this.OnStateChanged;
}

主布局:

@inherits LayoutComponentBase

<PageTitle>BlazorApp3</PageTitle>

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4 auth">
            <LoginDisplay />
            <a href="https://learn.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            <Loading />
            @Body
        </article>
    </main>
</div>

最后是演示页面:

@page "/"
@inject AppStateService appStateService; 

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@code{

    protected async override Task OnInitializedAsync()
    {
        this.appStateService.IsLoaded = false;
        // emulate an async loading event 
        await Task.Delay(2000);
        this.appStateService.IsLoaded = true;
    }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.