我有一个自定义组件,其中有一个名为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: Object reference not set to an instance of an object 错误。
如果我切换到使用后续的渲染,它就可以正常工作:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(!firstRender)
{
tabSet.TabChanged += TabChanged;
}
}
当然,这种方法很草率,每次渲染时会堆叠多个事件处理程序,我将对其进行解雇。
我如何在第一次渲染时仅分配一次引用?我正在按照此处所述的文档进行操作。
编辑
这是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的一个示例中获取的,可以在此处找到。
编辑2
这里是调试器显示tabSet在第一次渲染时为null:
在后续渲染中不为null:
if(firstRender) { tabSet.TabChanged += TabChanged; }
时没有得到空异常。TabChanged
是一个委托吗?你能否展示一下如何重现这个问题? - itminus<TabSet @ref="tabSet">
是否在if (
里面? - dani herrera