You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Blazor Virtualize组件虚拟化时如何保留行组件编辑状态

问题根因

你遇到的是Blazor Virtualize组件的固有特性:该组件仅渲染可视区域内的元素,滚动出可视区的DOM和对应子组件实例会被直接销毁,滚动回来时会根据数据源重新创建组件实例,所以存储在TableRow子组件内部的局部状态(编辑开关、未保存输入内容)自然会丢失。

核心解决思路:不要将临时状态存储在TableRow子组件的局部变量中,将状态上移到不会被虚拟化销毁的上层,和行数据绑定存储。


具体实现方案

方案1:在原员工模型中扩展临时状态字段(最简便)

给你的Employee实体类新增临时状态字段,可加序列化忽略标记避免提交到后端:

public class Employee
{
    // 原有字段
    public Guid EmployeeId { get; set; }
    public string Name { get; set; }
    // ... 其他原有字段

    // 新增临时状态字段
    [JsonIgnore]
    public bool IsEditing { get; set; }
    [JsonIgnore]
    public Employee TempEditData { get; set; }
}

子组件直接绑定行数据上的状态,不再自己维护局部状态:

<!--TableRow 子组件修改后-->
@if(rowModel.IsEditing)
{
  <tr>    
    <td><input @bind="@rowModel.TempEditData.Name" /></td>
    <td>...</td>
    <td><button @onclick="SaveData">保存</button></td>
  </tr>
}
else 
{
  <tr>    
    <td>@rowModel.Name</td>
    <td>...</td>
    <td><button @onclick="EnableEditing">编辑</button></td>
  </tr>
}

@code {
    [Parameter]
    public Employee rowModel { get; set; }

    void EnableEditing()
    {
        // 初始化临时编辑副本
        rowModel.TempEditData = new Employee()
        {
            Name = rowModel.Name,
            // 其他字段复制
        };
        rowModel.IsEditing = true;
    }

    void SaveData()
    {
        // 把临时数据覆盖到原数据
        rowModel.Name = rowModel.TempEditData.Name;
        // 其他字段覆盖
        rowModel.IsEditing = false;
        rowModel.TempEditData = null;
    }
}

方案2:父组件单独维护临时状态字典(不改原有模型)

如果不想侵入原有Employee模型,可在父组件单独维护状态存储:

// 父组件代码
public Dictionary<Guid, RowTempState> _editStateDict = new();

public class RowTempState
{
    public bool IsEditing { get; set; }
    public string TempName { get; set; }
    // 其他需要临时存储的编辑字段
}

父组件传值给子组件时,额外传入对应行的状态,同时给子组件加@key避免状态错位:

<!--Parent Component 修改后-->
<table>
  <thead>[...]</thead>
  <tbody>
    <Virtualize Items="employeeData">
      <TableRow 
        @key="context.EmployeeId" 
        rowModel="context" 
        EditState="_editStateDict.TryGetValue(context.EmployeeId, out var state) ? state : new()"
      />
    </Virtualize>
  </tbody>
</table>

子组件的状态都绑定到传入的EditState对象即可。


额外优化提示

如果你的业务只允许同时存在一个编辑行,不需要维护字典,父组件直接存Guid? _editingEmployeeId和对应的临时编辑对象即可,子组件只需要判断当前行ID是否等于_editingEmployeeId即可切换编辑状态。

内容的提问来源于stack exchange,提问作者UnusualWays

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 07:27:03