首次渲染时Blazor组件参考为空

我有一个自定义组件,带有一个名为TabChanged的事件action。在我的Razor页面中,我将对它的引用设置如下:

<TabSet @ref="tabSet">
 ...
</TabSet>

@code {
    private TabSet tabSet;   
    ...
}

OnAfterRenderAsync 方法中,我为事件分配处理程序:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if(firstRender)
    {
        tabSet.TabChanged += TabChanged;
    }       
}

页面第一次呈现时,出现 System.NullReferenceException:对象引用未设置为对象实例的错误

如果我切换为使用后续渲染,则效果很好:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if(!firstRender)
    {
        tabSet.TabChanged += TabChanged;
    }       
}

但是当然这很草率,我将在渲染期间触发多个事件处理程序,以触发它们。

如何在第一次渲染时一次分配参考?我正在按照here

的说明操作文档

编辑

这是TabSet.razor文件:

@using Components.Tabs

<!-- Display the tab headers -->
<CascadingValue Value="this">
    <ul class="nav nav-tabs">
        @ChildContent
    </ul>
</CascadingValue>

<!-- Display body for only the active tab -->
<div class="nav-tabs-body" style="padding:15px; padding-top:30px;">
    @activetab?.ChildContent
</div>

@code {

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    public ITab activetab { get; private set; }

    public event action TabChanged;


    public void AddTab(ITab tab)
    {
        if (activetab == null)
        {
            Setactivetab(tab);
        }
    }

    public void Removetab(ITab tab)
    {
        if (activetab == tab)
        {
            Setactivetab(null);
        }
    }

    public void Setactivetab(ITab tab)
    {
        if (activetab != tab)
        {
            activetab = tab;
            NotifyStateChanged();
            StateHasChanged();
        }
    }

    private void NotifyStateChanged() => TabChanged?.Invoke();

}

TabSet也使用Tab.razor:

@using Components.Tabs
@implements ITab

<li>
    <a @onclick="activate" class="nav-link @TitleCssClass" role="button">
        @Title
    </a>
</li>

@code {
    [CascadingParameter]
    public TabSet ContainerTabSet { get; set; }

    [Parameter]
    public string Title { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }


    private string TitleCssClass => ContainerTabSet.activetab == this ? "active" : null;

    protected override void OnInitialized()
    {
        ContainerTabSet.AddTab(this);
    }

    private void activate()
    {
        ContainerTabSet.Setactivetab(this);
    }
}

和ITab.cs界面

using microsoft.AspNetCore.Components;

namespace PlatformAdmin.Components.Tabs
{
    public interface ITab
    {
        RenderFragment ChildContent { get;  }

        public string Title { get; }
    }
}

它取自史蒂夫·桑德森(Steve Sanderson)的一个例子,here

编辑2

这是调试器,显示在第一次渲染时tabSet为null:

首次渲染时Blazor组件参考为空

在其他渲染器上也不为空:

首次渲染时Blazor组件参考为空

guoshuzhengsz 回答:首次渲染时Blazor组件参考为空

就我而言,它是通过初始化对象来解决的

EX: private TabSet tabSet = new TabSet();

,

在第一个渲染中,组件被渲染。第一次渲染后,引用对象就是组件。因此,第一次,component的ref为null(非ref)。 有关更多详细信息,请参见here

中的详细信息

仅在呈现组件之后填充tabSet变量,并且其输出包括TabSet元素。在那之前,没有什么可参考的。要在组件完成渲染后操纵组件引用,请使用OnAfterRenderAsync或OnAfterRender方法。

,

正如Dani Herrera在评论中指出的,这可能是由于组件带有if / else语句而确实如此。以前,如果对象为null,我会将组件隐藏起来:

@if(Account != null)
{
    <TabSet @ref="tabSet">
     ...
    </TabSet>
}

为简洁起见,我忽略了这一点,并错误地认为该问题不是有条件的。我非常错误,因为在第一次渲染时该对象为null,因此该组件不存在!所以要小心。我通过将条件转移到组件中的各个部分来解决了该问题:

@if(Account != null)
{
<TabSet @ref="tabSet">
    @if(Account != null)
    {
        <Tab>
         ...
        </Tab>
        <Tab>
         ...
        </Tab>
    }
</TabSet>
本文链接:https://www.f2er.com/3113419.html

大家都在问