Blazor DynamicComponent点击事件获取对应行数据实现方案
Blazor动态组件表格行数据获取方案
通过TableTemplate自动注入行上下文的方式即可实现点击按钮时获取对应行的宠物名,该方案复用性最高,不需要业务页面重复传参,以下是完整实现步骤:
步骤1:修正基础定义错误
- 调整
ComponentMetadata类:原类中存储组件类型的Name属性为字符串类型,和DynamicComponent要求的Type类型参数不匹配,直接修改为存储Type类型,避免字符串解析类型的加载问题:
public class ComponentMetadata { // 原Name属性改为ComponentType,直接存组件类型 public Type? ComponentType { get; set; } public Dictionary<string, object> Parameters { get; set; } = new Dictionary<string, object>(); }
- 调整
MyButton组件:原组件点击方法默认接收的是Blazor注入的MouseEventArgs鼠标事件参数,无法直接拿到行数据,新增行上下文参数存储关联数据,点击时回传即可:
<button type="button" class="@Style" @onclick="BtnClick"> @Text </button> @code { [Parameter] public string Style { get; set; } [Parameter] public string Text { get; set; } // 新增:存储当前行关联的业务数据 [Parameter] public object? RowContext { get; set; } [Parameter] public EventCallback<object> OnBtnClick { get; set; } private async Task BtnClick() { // 点击时回传关联的行数据 await OnBtnClick.InvokeAsync(RowContext!); } }
步骤2:修改TableTemplate自动注入行数据
在遍历行配置渲染动态组件时,由表格组件自动把当前行的DataItem注入到动态组件的参数中,不需要业务页面手动绑定,避免漏传:
<table class="table"> <thead> <tr>@TableHeader</tr> </thead> <tbody> @foreach (var RowTemplateConfig in RowTemplateConfigs) { if (RowTemplateConfig.DataItem is not null) { <tr> <td> @RowTemplateConfig.DataItem </td> @if(RowTemplateConfig.ComponentMetadata is not null) { <td> <DynamicComponent Type="@RowTemplateConfig.ComponentMetadata.ComponentType" Parameters="@GetMergedParameters(RowTemplateConfig)" /> </td> } </tr> } } </tbody> </table> @code { public class RowTemplateConfig { public ComponentMetadata ComponentMetadata { get; set;} = new(); public string DataItem { get; set; } = string.Empty; } [Parameter] public RenderFragment? TableHeader { get; set; } [Parameter] public List<RowTemplateConfig> RowTemplateConfigs {get; set;} = new(); // 合并原有参数和自动注入的行上下文 private Dictionary<string, object> GetMergedParameters(RowTemplateConfig rowConfig) { var paramDict = new Dictionary<string, object>(rowConfig.ComponentMetadata.Parameters); // 约定参数名为RowContext,所有需要拿行数据的动态组件都定义同名参数即可 paramDict["RowContext"] = rowConfig.DataItem; return paramDict; } }
注意:原代码中TableTemplate标签上写的
TItem =string没有对应的泛型定义,会编译报错,直接删除即可。
步骤3:调整业务页面代码
修正原配置初始化的语法错误(字典项缺逗号、typeof写法不完整),回调中直接拿传入的行数据即可:
@page "/pets1" <h1>Pets</h1> <TableTemplate RowTemplateConfigs="@RowTemplateConfigs"> <TableHeader> <th>Name</th> <th>Operation</th> </TableHeader> </TableTemplate> @code { private List<RowTemplateConfig> RowTemplateConfigs = new() { new RowTemplateConfig() { DataItem = "Bigglesworth", ComponentMetadata = new() { ComponentType = typeof(MyButton), Parameters = new Dictionary<string, object>() { { nameof(MyButton.Style), "btn btn-outline-success" }, { nameof(MyButton.OnBtnClick), EventCallback.Factory.Create<object>(this, OnTestClick)}, { nameof(MyButton.Text), "Hi"} } } }, new RowTemplateConfig() { DataItem = "Saberhagen", ComponentMetadata = new() { ComponentType = typeof(MyButton), Parameters = new Dictionary<string, object>() { { nameof(MyButton.Style), "btn btn-outline-success" }, { nameof(MyButton.OnBtnClick), EventCallback.Factory.Create<object>(this, OnTestClick)}, { nameof(MyButton.Text), "Hi"} } } }, }; private async Task OnTestClick(object rowData) { // 这里拿到的就是点击按钮对应行的宠物名称 string currentPetName = (string)rowData; // 后续业务逻辑直接用currentPetName即可 await Task.CompletedTask; } }
备选轻量方案(无需修改TableTemplate)
如果不想调整表格组件逻辑,可以在初始化每一行配置时,通过C#闭包直接捕获当前行的DataItem,绑定专属回调:
new RowTemplateConfig() { DataItem = "Bigglesworth", ComponentMetadata = new() { ComponentType = typeof(MyButton), Parameters = new Dictionary<string, object>() { { nameof(MyButton.Style), "btn btn-outline-success" }, // 闭包捕获当前DataItem,点击时直接传入 { nameof(MyButton.OnBtnClick), EventCallback.Factory.Create<MouseEventArgs>(this, () => OnTestClick("Bigglesworth"))}, { nameof(MyButton.Text), "Hi"} } } }
对应的回调方法直接接收string类型参数即可,缺点是动态数据场景下需要手动为每一项绑定值,容易出错。
内容的提问来源于stack exchange,提问作者Nb777
相关产品推荐
相关产品推荐

