Blazor 复选框过滤奇怪的渲染

Blazor checkbox filtering strange rendering

我有一个 CheckModel 类 列表,其属性为 int Id 和 bool IsChecked。我想根据 IsChecked 属性.

过滤它们

当我在过滤已检查项目的 foreach 循环中呈现它们时,出现错误行为。该项目已从视图中删除,但在视图中占据它位置的下方项目呈现为选中状态,而实际上它不是。

这是显示此行为的 gif:

似乎 Blazor 的渲染在某种程度上落后于复选框。 这是代码:

@page "/"

<div>
    <input id="filter-collected-checkbox" type="checkbox" @bind="FilterChecked" />
    <label for="filter-collected-checkbox">Filter</label>
</div>
@foreach((CheckModel item, int index) in CheckModels.Where(x=>!FilterChecked || !x.IsChecked).Select((x,i)=>(x,i)))
{
    <div style="display: flex">
        @item.Id
        <input id="item-collected-checkbox-@index" type="checkbox" checked="@item.IsChecked" @onchange="(e)=>MarkItemCollected(e,item)"/>
    </div>
}
@code {
    public List<CheckModel> CheckModels { get; set; }
    public bool FilterChecked { get; set; }
    protected override void OnInitialized()
    {
        CheckModels = new List<CheckModel>();
        for (int i = 0; i < 10; i++)
        {
            CheckModels.Add(new CheckModel() { Id = i });
        }
    }

    private void MarkItemCollected(ChangeEventArgs e, CheckModel item)
    {
        item.IsChecked = (bool)e.Value;
    }
}

我将 html checked-attribute 与 @onchange 一起使用的原因是因为我想在绑定发生后有一个方法。如果我将@bind=IsChecked 与@onclick=Method 一起使用,@onclick 在绑定之前被触发。

有人知道如何解决这个问题吗?

您需要为循环内容使用@key,以便渲染引擎知道哪些项目需要更新。

 <div @key=@item.Id style="display: flex">

文档是here

工作REPL

仅供参考:

<div>
    <input id="filter-collected-checkbox" type="checkbox" @bind="filterChecked" />
    <label for="filter-collected-checkbox">Filter</label>
</div>

@foreach(var item in FilteredItems)
{
    <div @key=@item.Id style="display: flex">
        @item.Id
        <input id="item-collected-checkbox-@item.Id" type="checkbox" @bind="@item.IsChecked" />
    </div>
}

@code {
    List<CheckModel> checkModels = Enumerable.Range(0,10)            
        .Select(i => new CheckModel() { Id = i })
        .ToList(); 
        
    bool filterChecked;
    
    IEnumerable<CheckModel> FilteredItems => 
        filterChecked ? checkModels.Where(x=> !x.IsChecked) : checkModels;
}

呈现 same result.