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

使用Syncfusion控件的Blazor Grid如何传递主键到对话框编辑记录

问题1:获取编辑选中记录的主键

Syncfusion SfGrid提供了GetSelectedRecordsAsync()方法可以直接获取当前选中的行数据,你只需在编辑按钮的点击逻辑中调用该方法即可拿到主键,同时要注意你原有代码中if判断没有加花括号的语法问题,会导致逻辑错误。
修改My_Templates.razor的OnClicked方法:

public async Task OnClicked(Syncfusion.Blazor.Navigations.ClickEventArgs Args)
{
    if (Args.Item.Id == "Add")
    {
        // 新增场景传递空的新对象
        dialog.Title = "这是新增标题";
        dialog.Text = "这是新增内容";
        // 给子组件传新的空Order对象
        dialog.CurrentOrder = new Order();
        dialog.OpenDialog();
    }

    if (Args.Item.Id == "Edit")
    {
        // 获取选中行
        var selectedRecords = await Grid.GetSelectedRecordsAsync();
        if (selectedRecords == null || !selectedRecords.Any())
        {
            // 这里可以加未选中行的提示逻辑
            return;
        }
        var editOrder = selectedRecords.First();
        dialog.Title = "这是编辑标题";
        dialog.Text = "这是编辑内容";
        // 直接传递选中的完整记录对象,不用只传主键
        dialog.CurrentOrder = editOrder;
        dialog.OpenDialog();
    }
}

问题2:子组件获取记录的方式

直接传递完整记录对象的效率更高,无需子组件再根据主键二次查询,同时你需要调整子组件的参数和数据绑定逻辑,修正原有代码的错误:

  1. 首先删除ReusableDialog.razor中冗余的Employee类依赖,统一使用父组件定义的Order类(也可以把Order抽成公共类放在单独的文件里,两边都引用)
  2. 子组件新增EventCallback参数用于把编辑后的结果回传给父组件,删除子组件中new父组件实例的错误代码,Blazor父子组件通信不要直接new实例,要用参数和回调。

修改后的ReusableDialog.razor代码示例:

@using Syncfusion.Blazor.Popups
@* 引用你Order类所在的命名空间 *@

<div id="DialogTarget">
    <SfDialog Target="#DialogTarget" Width="1200px" IsModal="true" ShowCloseIcon="true" @bind-Visible="@IsOpen">
        <DialogTemplates>
            <Header><h4 class="modal-title">@Title</h4></Header>
            <Content>
                <EditForm Model="@CurrentOrder" OnValidSubmit="@HandleValidSubmit">
                    <DataAnnotationsValidator />
                    <label>Owner</label>
                    <InputText id="owner" @bind-Value="CurrentOrder.owner" class="form-control" />
                    <label>Users</label>
                    <InputText id="users" @bind-Value="CurrentOrder.users" class="form-control" />
                    <label>Description</label>
                    <InputTextArea @bind-Value="CurrentOrder.description" class="form-control" rows="4" />
                    <label>Fund Type</label>
                    <p></p>
                    <InputRadioGroup @bind-Value="CurrentOrder.fundType" class="form-control">
                        @foreach (var option in rdOptions)
                        {
                            <InputRadio Value="option" /> @option <br />
                        }
                    </InputRadioGroup>
                </EditForm>
            </Content>
        </DialogTemplates>
        <DialogButtons>
            <DialogButton Content="OK" IsPrimary="true" OnClick="@OkClick" />
            <DialogButton Content="Cancel" IsPrimary="false" OnClick="@CancelClick" />
        </DialogButtons>
    </SfDialog>
</div>

@code {
    [Parameter]
    public string Title { get; set; }
    [Parameter]
    public string Text { get; set; }
    // 替换原来的Employee参数,统一用Order
    [Parameter]
    public Order CurrentOrder { get; set; } = new Order();
    [Parameter]
    public string ButtonText { get; set; } = "Save";
    // 回调父组件的事件,返回编辑结果和操作类型
    [Parameter]
    public EventCallback<(bool IsConfirmed, Order ResultOrder)> OnClose { get; set; }
    [Parameter]
    public bool IsOpen { get; set; } = false;

    List<string> rdOptions = new List<string> { " Fund Type 1", " Fund Type 2", " Fund Type 3" };

    public void OpenDialog()
    {
        IsOpen = true;
        StateHasChanged();
    }

    private Task HandleValidSubmit()
    {
        // 校验通过直接触发确认回调
        return OkClick();
    }

    private async Task OkClick()
    {
        IsOpen = false;
        StateHasChanged();
        await OnClose.InvokeAsync((true, CurrentOrder));
    }

    private async Task CancelClick()
    {
        IsOpen = false;
        StateHasChanged();
        await OnClose.InvokeAsync((false, null));
    }
}

父组件接收回调更新数据

父组件中给ReusableDialog绑定OnClose回调,处理新增/编辑后的数据源更新逻辑:

<ReusableDialog @ref="dialog" OnClose="@HandleDialogClose"></ReusableDialog>

对应的后台逻辑:

private async Task HandleDialogClose((bool IsConfirmed, Order ResultOrder) result)
{
    if (!result.IsConfirmed || result.ResultOrder == null)
    {
        return;
    }
    if (result.ResultOrder.templateID == 0)
    {
        // 新增场景:给新记录生成主键,添加到数据源
        result.ResultOrder.templateID = Orders.Max(o => o.templateID) + 1;
        Orders.Add(result.ResultOrder);
    }
    else
    {
        // 编辑场景:找到原有记录替换
        var existOrder = Orders.FirstOrDefault(o => o.templateID == result.ResultOrder.templateID);
        if (existOrder != null)
        {
            existOrder.owner = result.ResultOrder.owner;
            existOrder.users = result.ResultOrder.users;
            existOrder.description = result.ResultOrder.description;
            existOrder.fundType = result.ResultOrder.fundType;
        }
    }
    // 刷新Grid
    await Grid.Refresh();
}

通用设计模式建议

  • 模型统一:同一份业务数据不要定义多个类,抽成公共的模型类放在单独的项目文件中统一引用
  • 父子组件通信遵循Blazor规范:父传子用[Parameter],子传父用EventCallback,不要在子组件中创建父组件的实例
  • 复用组件只做通用逻辑:对话框组件只负责数据收集和校验,不要耦合具体的业务保存逻辑,所有业务逻辑都放在父组件处理,提高组件复用性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:18:03