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

如何创建可复用Blazor Radzen DataGrid自定义组件及错误解决

问题描述

需要创建可复用的Blazor Radzen DataGrid组件,支持基于任意类动态渲染数据。以Customer类和DummyData模拟数据为例,尝试封装CustomDataGrid组件时遇到编译错误,错误信息如下:

Severity    Code    Description Project File    Line    Suppression State   Details
Error (active)  CS1061  'RadzenDataGridColumn<Customer>' does not contain a definition for 'AddAttribute' and no accessible extension method 'AddAttribute' accepting a first argument of type 'RadzenDataGridColumn<Customer>' could be found (are you missing a using directive or an assembly reference?)    TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 32      
Error (active)  CS0103  The name 'OnUpdateRow' does not exist in the current context    TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 6       
Error (active)  CS0103  The name 'AddNewCustomer' does not exist in the current context TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 8       
Error (active)  CS1643  Not all code paths return a value in lambda expression of type 'RenderFragment<RadzenDataGridColumn<Customer>>' TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 29      
Error (active)  CS1061  'RadzenDataGridColumn<Customer>' does not contain a definition for 'OpenComponent' and no accessible extension method 'OpenComponent' accepting a first argument of type 'RadzenDataGridColumn<Customer>' could be found (are you missing a using directive or an assembly reference?)  TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 31      
Error (active)  CS1061  'RadzenDataGridColumn<Customer>' does not contain a definition for 'CloseComponent' and no accessible extension method 'CloseComponent' accepting a first argument of type 'RadzenDataGridColumn<Customer>' could be found (are you missing a using directive or an assembly reference?)    TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 35      
Error (active)  CS1061  'RadzenDataGridColumn<Customer>' does not contain a definition for 'AddAttribute' and no accessible extension method 'AddAttribute' accepting a first argument of type 'RadzenDataGridColumn<Customer>' could be found (are you missing a using directive or an assembly reference?)    TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 34      
Error (active)  CS1061  'RadzenDataGridColumn<Customer>' does not contain a definition for 'AddAttribute' and no accessible extension method 'AddAttribute' accepting a first argument of type 'RadzenDataGridColumn<Customer>' could be found (are you missing a using directive or an assembly reference?)    TestingDynamicEditableTable D:\etc\Practice\TestingDynamicEditableTable\TestingDynamicEditableTable\Pages\Counter.razor 33      

现有基础代码

DummyData.cs

using Bogus;
using System;
using System.Collections.Generic;

namespace TestingDynamicEditableTable.Data
{
    public static class DummyData
    {
        private static readonly Faker<Customer> CustomerFaker = new Faker<Customer>()
            .RuleFor(c => c.CustomerID, f => f.Random.AlphaNumeric(5))
            .RuleFor(c => c.CompanyName, f => f.Company.CompanyName())
            .RuleFor(c => c.ContactName, f => f.Person.FullName);

        public static IEnumerable<Customer> GetCustomers(int count = 50)
        {
            return CustomerFaker.Generate(count);
        }
    }
}

解决方案

1. 重构可复用CustomDataGrid组件

采用插槽式设计传递自定义列,封装通用编辑、删除、新增逻辑,暴露必要事件供调用页处理业务逻辑:

@typeparam TItem
@using Radzen

<RadzenDataGrid @ref="DataGridRef" TItem="TItem" 
                AllowPaging="true" PageSize="5" AllowSorting="true" 
                EditMode="@EditMode" AllowGrouping="true" AllowColumnResize="true"
                Data="@Items" ColumnWidth="200px"
                RowUpdate="@RowUpdate" RowCreate="@RowCreate">
    <Columns>
        <!-- 接收调用页传递的自定义列 -->
        @ChildContent
        <!-- 通用操作列(编辑/删除/保存/取消) -->
        <RadzenDataGridColumn TItem="TItem" Context="item" Filterable="false" Sortable="false" 
                              TextAlign="TextAlign.Right" Frozen="true" FrozenPosition="FrozenColumnPosition.Right">
            <Template Context="item">
                <RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" 
                              Size="ButtonSize.Medium" Click="@(() => EditRow(item))" @onclick:stopPropagation="true" />
                <RadzenButton Icon="delete" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" 
                              Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(() => DeleteRow(item))" />
            </Template>
            <EditTemplate Context="item">
                <RadzenButton Icon="save" ButtonStyle="ButtonStyle.Success" Variant="Variant.Flat" 
                              Size="ButtonSize.Medium" Click="@(() => SaveRow(item))" />
                <RadzenButton Icon="cancel" ButtonStyle="ButtonStyle.Light" Variant="Variant.Flat" 
                              Size="ButtonSize.Medium" class="my-1 ms-1" Click="@(() => CancelEdit(item))" />
            </EditTemplate>
        </RadzenDataGridColumn>
    </Columns>
</RadzenDataGrid>

@code {
    [Parameter] public IEnumerable<TItem> Items { get; set; }
    [Parameter] public RenderFragment ChildContent { get; set; } // 自定义列插槽
    [Parameter] public EventCallback<TItem> RowUpdate { get; set; }
    [Parameter] public EventCallback<TItem> RowCreate { get; set; }
    [Parameter] public EventCallback<TItem> RowDelete { get; set; }
    [Parameter] public DataGridEditMode EditMode { get; set; } = DataGridEditMode.Single;

    public RadzenDataGrid<TItem> DataGridRef { get; set; }
    private TItem _editingItem;

    public void EditRow(TItem item)
    {
        _editingItem = item;
        DataGridRef.EditRow(item);
    }

    public async Task SaveRow(TItem item)
    {
        await DataGridRef.UpdateRow(item);
    }

    public void CancelEdit(TItem item)
    {
        _editingItem = default;
        DataGridRef.CancelEditRow(item);
    }

    public void InsertRow(TItem item)
    {
        DataGridRef.InsertRow(item);
    }

    public async Task DeleteRow(TItem item)
    {
        await RowDelete.InvokeAsync(item);
        DataGridRef.Reload();
    }
}

2. 修改Counter.razor使用复用组件

在调用页中传递自定义列,实现业务相关的事件逻辑:

@page "/counter"
@using TestingDynamicEditableTable.Data
@using System.Collections.Generic
@using System.Linq
@using Radzen

<CustomDataGrid TItem="Customer" Items="@customers" 
                RowUpdate="@OnUpdateRow" RowCreate="@OnCreateRow" RowDelete="@OnDeleteRow"
                @ref="customGrid">
    <!-- 自定义列定义,保留原有编辑模板 -->
    <RadzenDataGridColumn TItem="Customer" Property="CustomerID" Title="ID" Width="40px" Frozen="true" />
    <RadzenDataGridColumn TItem="Customer" Property="CompanyName" Title="Company Name" Width="280px">
        <EditTemplate Context="customer">
            <RadzenTextBox @bind-Value="customer.CompanyName" Style="width:100%" />
        </EditTemplate>
    </RadzenDataGridColumn>
    <RadzenDataGridColumn TItem="Customer" Property="ContactName" Title="Contact Name" Width="220px">
        <EditTemplate Context="customer">
            <RadzenTextBox @bind-Value="customer.ContactName" Style="width:100%" />
        </EditTemplate>
    </RadzenDataGridColumn>
</CustomDataGrid>

<RadzenButton Text="Add New Customer" Click="AddNewCustomer" />

@code {
    private CustomDataGrid<Customer> customGrid;
    private List<Customer> customers;
    private Customer _editingCustomer;

    protected override void OnInitialized()
    {
        customers = DummyData.GetCustomers().ToList();
    }

    private void AddNewCustomer()
    {
        var newCustomer = new Customer();
        customers.Add(newCustomer);
        customGrid.InsertRow(newCustomer);
    }

    private async Task OnUpdateRow(Customer customer)
    {
        // 实现数据更新逻辑(比如调用API保存)
        _editingCustomer = null;
    }

    private async Task OnCreateRow(Customer customer)
    {
        // 实现数据新增逻辑
    }

    private async Task OnDeleteRow(Customer customer)
    {
        customers.Remove(customer);
    }
}

错误原因说明

  • 原代码误用RenderFragment<RadzenDataGridColumn<TItem>>类型,正确方式是使用RenderFragment作为插槽传递列内容
  • 修改后的Counter.razor中注释掉了事件处理方法,导致编译报错,需恢复完整实现
  • 手动构建RenderFragment时混淆了RenderTreeBuilder方法与组件实例方法,OpenComponent等是RenderTreeBuilder的API,不能直接调用组件实例的该方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:45:54