Blazor封装FluentDataGrid时,如何通过RenderFragment<TItem>传入列模板并提供上下文对象?
我明白你现在的困扰——刚接触FluentUI的DataGrid,封装时想把列定义通过RenderFragment从外部传入,却卡在上下文绑定的问题上,这类泛型参数和上下文传递的坑确实容易踩,给你梳理下具体的调整思路和方案:
问题根源分析
你原来把GridRow定义成了RenderFragment<TItem>,但FluentDataGrid的列定义(比如PropertyColumn)本身不需要直接接收TItem实例作为上下文——因为PropertyColumn的Property表达式(比如@(p => p.Surname))已经通过泛型参数TGridItem="TItem"和组件完成了类型绑定,真正需要的是把列的集合作为普通RenderFragment传入,而非带TItem参数的版本。
具体修改步骤
1. 调整封装组件的参数定义
把原来的RenderFragment<TItem> GridRow改成普通的RenderFragment参数,语义上更清晰的话可以命名为Columns:
[Parameter] public RenderFragment Columns { get; set; }
2. 修正FluentDataGrid的ChildContent绑定
原来在FluentDataGrid里直接调用@GridRow()的方式不对,应该直接把传入的Columns渲染到FluentDataGrid内部,它会自动处理列与TItem的关联:
<div class="@sMainClass" tabindex="-2" @ref="this.oElementReference"> @this.SearchCriteria @this.HeaderControls <FluentDataGrid @ref="this.ucFluentGrid" AutoFit="true" AutoItemsPerPage="@this.bAutoCalculateRowCount" Style="width: 100%;overflow-y:hidden;" ResizableColumns="true" Items="@this.DataService.DataServiceItems.AsQueryable()" Pagination="@this.Pagination" TGridItem="TItem" OnRowClick="@this.FluentRowClick" OnRowDoubleClick="@this.FluentRowDoubleClick"> <!-- 直接渲染外部传入的列定义 --> @Columns </FluentDataGrid> <FluentPaginator State="@this.Pagination" /> </div>
3. 外部使用时正常定义列模板
现在你可以在使用封装组件的地方,直接通过<Columns>标签传入PropertyColumn或其他列类型,上下文会自动通过泛型参数TItem绑定:
<YourDataGridWrapper TItem="Person" ...> <Columns> <PropertyColumn Title="Surname" Property="@(p => p.Surname)" Sortable="true" /> <PropertyColumn Title="Forename" Property="@(p => p.Forename)" Sortable="true" /> <PropertyColumn Title="Date" Property="@(p => p.DateOfBirth)" Format="MM/dd/yyyy" Sortable="true" /> <PropertyColumn Title="Email" Property="@(p => p.Email)" Sortable="true" /> </Columns> </YourDataGridWrapper>
如果你确实需要带TItem上下文的自定义模板
如果之后需要用TemplateColumn渲染动态内容(比如根据行数据显示操作按钮),可以额外暴露一个RenderFragment<TItem>参数:
[Parameter] public RenderFragment<TItem> CustomRowTemplate { get; set; }
然后在封装组件的FluentDataGrid里添加对应的模板列,手动传递当前行的TItem上下文:
<FluentDataGrid ...> @Columns <!-- 自定义模板列,传递当前行的TItem上下文 --> <TemplateColumn Title="操作"> @context => CustomRowTemplate(context) </TemplateColumn> </FluentDataGrid>
外部使用时就能直接拿到当前行的上下文:
<YourDataGridWrapper TItem="Person"> <CustomRowTemplate> <FluentButton OnClick="@(() => HandleEdit(context))">编辑</FluentButton> </CustomRowTemplate> </YourDataGridWrapper>
额外注意点
- 确保封装组件是泛型组件(继承
ComponentBase并声明TItem约束,比如where TItem : class) - 记得初始化分页状态:在组件代码里添加
protected PaginationState<TItem> Pagination { get; set; } = new PaginationState<TItem>();
这样调整后,既能保留封装组件的通用回调(行点击、双击)和分页逻辑,又能灵活从外部传入列模板,上下文绑定也能正常工作了。
内容来源于stack exchange

