C# blazor中的ComponentReferenceCapture更新

C# blazor中的ComponentReferenceCapture更新,c#,blazor,C#,Blazor,在blazor示例中,我使用RenderFragment动态更新元素,并为每次更新捕获组件引用。在最初捕获元素时,它会正确地捕获组件引用。更新组件时,它将保留旧的componentReference。组件引用未正确更新 Index.razor @page "/" <button @onclick="AddContent">1st Update</button> <button @onclick="AddSecond

在blazor示例中,我使用RenderFragment动态更新元素,并为每次更新捕获组件引用。在最初捕获元素时,它会正确地捕获组件引用。更新组件时,它将保留旧的componentReference。组件引用未正确更新

Index.razor

@page "/"

<button @onclick="AddContent">1st Update</button>
<button @onclick="AddSecondContent">2nd Update</button>
<button @onclick="CheckContent">Check Update</button>
@DataContent

@code {
    RenderFragment DataContent { get; set; }
    List<Counter> CounterReference = new List<Counter>();
    void AddContent()
    {
        DataContent = (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) =>
        {
            int seq = 0;
            for(int i = 0; i < 3; i++)
            {
                builder.OpenComponent<Counter>(seq++);
                builder.AddComponentReferenceCapture(seq++, ins => { CounterReference.Add((Counter)ins); });
                builder.CloseComponent();
            }

        };
        InvokeAsync(StateHasChanged);
    }

    void AddSecondContent()
    {
        CounterReference.Clear();
        DataContent = (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) =>
        {
            int seq = 0;
            for (int i = 0; i < 2; i++)
            {
                builder.OpenComponent<Counter>(seq++);
                builder.AddComponentReferenceCapture(seq++, ins => { CounterReference.Add((Counter)ins); });
                builder.CloseComponent();
            }

        };
        InvokeAsync(StateHasChanged);
    }

    void CheckContent()
    {
        Console.WriteLine();
    }
}

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    public void IncrementCount()
    {
        currentCount++;
    }
}
@page/“
第一次更新
第二次更新
检查更新
@数据内容
@代码{
RenderFragment数据内容{get;set;}
列表计数器引用=新列表();
void AddContent()
{
数据内容=(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder)=>
{
int-seq=0;
对于(int i=0;i<3;i++)
{
OpenComponent(seq++);
AddComponentReferenceCapture(seq++,ins=>{CounterReference.Add((Counter)ins);});
builder.CloseComponent();
}
};
InvokeAsync(statehaschange);
}
void AddSecondContent()
{
CounterReference.Clear();
数据内容=(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder)=>
{
int-seq=0;
对于(int i=0;i<2;i++)
{
OpenComponent(seq++);
AddComponentReferenceCapture(seq++,ins=>{CounterReference.Add((Counter)ins);});
builder.CloseComponent();
}
};
InvokeAsync(statehaschange);
}
void CheckContent()
{
Console.WriteLine();
}
}
计数器.剃须刀

@page "/"

<button @onclick="AddContent">1st Update</button>
<button @onclick="AddSecondContent">2nd Update</button>
<button @onclick="CheckContent">Check Update</button>
@DataContent

@code {
    RenderFragment DataContent { get; set; }
    List<Counter> CounterReference = new List<Counter>();
    void AddContent()
    {
        DataContent = (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) =>
        {
            int seq = 0;
            for(int i = 0; i < 3; i++)
            {
                builder.OpenComponent<Counter>(seq++);
                builder.AddComponentReferenceCapture(seq++, ins => { CounterReference.Add((Counter)ins); });
                builder.CloseComponent();
            }

        };
        InvokeAsync(StateHasChanged);
    }

    void AddSecondContent()
    {
        CounterReference.Clear();
        DataContent = (Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) =>
        {
            int seq = 0;
            for (int i = 0; i < 2; i++)
            {
                builder.OpenComponent<Counter>(seq++);
                builder.AddComponentReferenceCapture(seq++, ins => { CounterReference.Add((Counter)ins); });
                builder.CloseComponent();
            }

        };
        InvokeAsync(StateHasChanged);
    }

    void CheckContent()
    {
        Console.WriteLine();
    }
}

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    public void IncrementCount()
    {
        currentCount++;
    }
}
@page”/counter
柜台
当前计数:@currentCount

点击我 @代码{ 私有int currentCount=0; 公共无效增量计数() { currentCount++; } }
在上面的示例中,我已经更新了数据内容,最初,我得到的反引用计数为3。在此之后,我清除了一个反引用,并更新了数据内容。在第二种情况下,我正在渲染2个计数器组件,它们在DOM中正确渲染。但我得到的反引用计数为0。在第二次更新中,如果我没有清除反引用,则其值为3。使其保留以前的值。我希望这个值是2


我做错了什么?

首先,这是一种创建组件的雄心勃勃的方法,很容易出错。大多数人犯的最大错误是使用一个变量来执行此操作。
seq++
请参见本文中的“序列号”部分,并且应使用静态递增计数。否则Blazor渲染器会对您正在更新的元素感到困惑。@Quango说了什么,但另外,当您在循环中渲染时,始终使用
@key
指令来唯一标识您正在渲染的元素-依赖于“序列”并不能保证微分算法始终捕获何时放置/创建新对象。这里可能发生的情况是Blazor认为您最初创建了3个计数器,然后只删除了一个(#3)-但它可以保留其他两个,并且由于它已经为这些计数器生成了引用,因此您不会得到新的引用。出于兴趣,您使用
RenderTreeBuilder
有什么原因吗?“你希望实现什么?”泉戈,谢谢。你的建议行得通。