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

如何在Blazor Ant Design Table中自定义GeneratedColumn列

解决Blazor Ant Design Table自动生成列添加编辑交互的问题

要给GenerateColumns自动生成的列添加编辑交互,核心是利用GenerateColumns的自定义列定义模板或全局列模板注入编辑逻辑,和自定义PropertyColumn的思路一致,只是需要把逻辑绑定到自动生成的列上。

方法一:为指定列自定义编辑模板(推荐)

这种方式可以精准控制需要编辑的列,还能为不同列使用不同的编辑组件(比如数字用InputNumber,文本用Input)。

1. 准备编辑状态缓存

先定义缓存结构维护每行的编辑状态:

private Dictionary<int, EditCacheItem> _editCache = new();

public class EditCacheItem
{
    public bool IsEditing { get; set; }
    // 可选:保存原始值用于取消编辑时恢复
    public Dictionary<string, object> OriginalValues { get; set; } = new();
}

在数据加载完成后初始化缓存:

protected override void OnInitialized()
{
    // 假设userDataSet是已加载的用户数据列表
    foreach (var user in userDataSet)
    {
        _editCache[user.UserID] = new EditCacheItem { IsEditing = false };
    }
}

2. 自定义列定义并绑定模板

创建IColumnDefinition<UserInfo>集合,为需要编辑的列指定模板:

private List<IColumnDefinition<UserInfo>> _columnDefinitions = new();

protected override void OnInitialized()
{
    // 为Exp列添加编辑模板
    _columnDefinitions.Add(new PropertyColumnDefinition<UserInfo>(nameof(UserInfo.Exp))
    {
        Width = "30%",
        Template = context =>
        {
            var user = context.Item;
            return builder =>
            {
                if (!_editCache[user.UserID].IsEditing)
                {
                    // 编辑状态:显示输入框
                    builder.OpenComponent<Input>(0);
                    builder.AddAttribute(1, nameof(Input.Type), "text");
                    builder.AddAttribute(2, nameof(Input.Value), user.Exp);
                    builder.AddAttribute(3, nameof(Input.ValueChanged), 
                        EventCallback.Factory.Create<string>(this, val => user.Exp = val));
                    builder.AddAttribute(4, nameof(Input.OnBlur), 
                        EventCallback.Factory.Create(this, () => StopEdit(user.UserID)));
                    builder.AddAttribute(5, nameof(Input.AutoFocus), true);
                    builder.CloseComponent();
                }
                else
                {
                    // 查看状态:显示文本并绑定点击编辑事件
                    builder.OpenElement(0, "div");
                    builder.AddAttribute(1, "class", "editable-cell-value-wrap");
                    builder.AddAttribute(2, "style", "padding-right:24px");
                    builder.AddAttribute(3, "onclick", 
                        EventCallback.Factory.Create(this, () => StartEdit(user.UserID)));
                    builder.AddContent(4, user.Exp);
                    builder.CloseElement();
                }
            };
        }
    });

    // 添加其他不需要编辑的自动生成列
    _columnDefinitions.Add(new PropertyColumnDefinition<UserInfo>(nameof(UserInfo.UserName)));
    _columnDefinitions.Add(new PropertyColumnDefinition<UserInfo>(nameof(UserInfo.Age)));
}

3. 实现编辑状态切换方法

private void StartEdit(int userId)
{
    var user = userDataSet.First(u => u.UserID == userId);
    // 保存原始值,可选用于取消编辑时恢复
    _editCache[userId].OriginalValues[nameof(UserInfo.Exp)] = user.Exp;
    _editCache[userId].IsEditing = true;
    StateHasChanged();
}

private void StopEdit(int userId)
{
    _editCache[userId].IsEditing = false;
    // 如需恢复原始值,取消下面注释
    // var user = userDataSet.First(u => u.UserID == userId);
    // user.Exp = (string)_editCache[userId].OriginalValues[nameof(UserInfo.Exp)];
    StateHasChanged();
}

4. 在Table中使用自定义列定义

<TabPane Tab="BasicInfo" Key="1">
    <Table TItem="UserInfo" DataSource="@userDataSet" RowClassName="@(_ => "editable-row")">
        <GenerateColumns Definitions="@_columnDefinitions" />
    </Table>
</TabPane>

方法二:全局列模板(批量处理所有自动生成列)

如果所有自动生成的列都需要相同的编辑逻辑,可以用ColumnTemplate统一处理,适合快速批量实现:

<TabPane Tab="BasicInfo" Key="1">
    <Table TItem="UserInfo" DataSource="@userDataSet" RowClassName="@(_ => "editable-row")">
        <GenerateColumns Range="0..">
            <ColumnTemplate>
                @{
                    var user = context.Item;
                    var prop = typeof(UserInfo).GetProperty(context.Column.PropertyName);
                    var currentValue = prop?.GetValue(user)?.ToString();
                }

                @if (!_editCache[user.UserID].IsEditing)
                {
                    <Input Type="text" 
                           Value="@currentValue"
                           ValueChanged="@(val => UpdateUserProperty(user.UserID, context.Column.PropertyName, val))"
                           OnBlur="()=>StopEdit(user.UserID)" 
                           AutoFocus />
                }
                else
                {
                    <div class="editable-cell-value-wrap" style="padding-right:24px" 
                         @onclick="()=>StartEdit(user.UserID)">
                        @currentValue
                    </div>
                }
            </ColumnTemplate>
        </GenerateColumns>
    </Table>
</TabPane>

补充属性更新方法:

private void UpdateUserProperty(int userId, string propName, string value)
{
    var user = userDataSet.First(u => u.UserID == userId);
    // 根据属性类型做转换,比如Age是int类型需要额外处理
    var prop = typeof(UserInfo).GetProperty(propName);
    if (prop != null)
    {
        var convertedValue = Convert.ChangeType(value, prop.PropertyType);
        prop.SetValue(user, convertedValue);
    }
}

注意事项

  • 如果数据是动态加载的(比如分页、搜索),要同步更新_editCache,避免出现KeyNotFound异常。
  • 方法二中的反射赋值需要处理不同数据类型的转换(比如数字、日期),可以根据实际业务场景扩展。
  • 编辑状态切换后需要调用StateHasChanged()触发组件重新渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:33:18