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

MVC中Kendo Spreadsheet本地数据绑定增删改及性能优化问题

Kendo Spreadsheet复杂表头场景下的数据绑定优化方案(含增删改实现)

问题核心

当前通过服务器端循环逐行生成单元格的方式,在数据量较大时会导致页面渲染性能急剧下降;而远程AJAX绑定会覆盖自定义的复杂合并表头,需要找到既能保留表头结构,又能高效加载数据并支持增删改的方案。

优化方案:客户端批量加载数据+预定义表头

核心思路:服务器端仅提供JSON格式数据接口,客户端初始化Spreadsheet时先渲染好复杂合并表头,再通过Spreadsheet的客户端API批量写入数据,同时通过事件监听和AJAX交互实现增删改操作。

1. 服务器端调整

ViewModel(中文注释)

public class ViewModel
{
    // 数据编号
    public int ID { get; set; }
    // 名称
    public int Name { get; set; }
    // 状态
    public string Status { get; set; }
}

控制器Action

// 渲染页面
public ActionResult Index()
{
    return View();
}

// 获取表格数据接口
public JsonResult GetSpreadsheetData()
{
    List<ViewModel> data = service.GetData();
    return Json(data, JsonRequestBehavior.AllowGet);
}

// 新增数据接口
[HttpPost]
public JsonResult AddData(ViewModel model)
{
    try
    {
        var newId = service.AddData(model);
        return Json(new { success = true, id = newId });
    }
    catch (Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

// 更新数据接口
[HttpPost]
public JsonResult UpdateData(ViewModel model)
{
    try
    {
        service.UpdateData(model);
        return Json(new { success = true });
    }
    catch (Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

// 删除数据接口
[HttpPost]
public JsonResult DeleteData(int id)
{
    try
    {
        service.DeleteData(id);
        return Json(new { success = true });
    }
    catch (Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

2. 视图端实现

在视图中先定义好复杂合并表头,再通过AJAX拉取数据并批量写入工作表,同时实现增删改的交互逻辑:

@model dynamic

@section body {
    @(Html.Kendo().Spreadsheet()
        .Columns(3)
        .Name("DataExcel")
        .HtmlAttributes(new { style = "width:auto; height: 770px;" })
        .Toolbar(true) // 启用工具栏,可自定义增删按钮
        .Sheetsbar(false)
        .Events(e => e
            .Select("onSelect")
            .Change("onDataChange"))
        .Sheets(sheets =>
        {
            sheets.Add()
            .Name("DataSheet")
            .Columns(columns =>
            {
                columns.Add().Width(50);
                columns.Add().Width(100);
                columns.Add().Width(100);
            })
            .Rows(rows =>
            {
                // 自定义复杂合并表头(示例结构,根据实际需求调整)
                rows.Add().Height(60).Cells(cells =>
                {
                    // 合并第1行3列作为主标题
                    cells.Add()
                        .Value("业务数据汇总")
                        .HorizontalAlign(SpreadsheetHorizontalAlign.Center)
                        .VerticalAlign(SpreadsheetVerticalAlign.Center)
                        .Bold(true)
                        .ColSpan(3);
                });
                rows.Add().Height(40).Cells(cells =>
                {
                    cells.Add().Value("编号").Bold(true).HorizontalAlign(SpreadsheetHorizontalAlign.Center);
                    cells.Add().Value("名称").Bold(true).HorizontalAlign(SpreadsheetHorizontalAlign.Center);
                    cells.Add().Value("状态").Bold(true).HorizontalAlign(SpreadsheetHorizontalAlign.Center);
                });
            });
        })
    )

    <script>
        $(document).ready(function() {
            var spreadsheet = $("#DataExcel").data("kendoSpreadsheet");
            var sheet = spreadsheet.activeSheet();

            // 加载数据
            $.ajax({
                url: "@Url.Action("GetSpreadsheetData")",
                type: "GET",
                success: function(data) {
                    if (!data || data.length === 0) return;

                    // 从第3行开始写入数据(前2行为表头)
                    const startRow = 2;
                    // 将数据转换为二维数组,方便批量写入
                    const dataRows = data.map(item => [item.ID, item.Name, item.Status]);

                    // 批量写入数据到工作表
                    sheet.range(startRow, 0, dataRows.length, 3).values(dataRows);

                    // 统一设置数据行样式
                    sheet.range(startRow, 0, dataRows.length, 3)
                        .verticalAlign("center")
                        .color("black");
                    // 状态列加粗
                    sheet.range(startRow, 2, dataRows.length, 1).bold(true);
                }
            });
        });

        // 数据修改事件监听
        function onDataChange(e) {
            const range = e.range;
            const sheet = e.sender.activeSheet();
            const rowIndex = range.top;

            // 跳过表头行
            if (rowIndex < 2) return;

            // 获取当前行完整数据
            const rowData = sheet.range(rowIndex, 0, 1, 3).values()[0];
            const updateModel = {
                ID: rowData[0],
                Name: rowData[1],
                Status: rowData[2]
            };

            // 提交更新请求
            $.ajax({
                url: "@Url.Action("UpdateData")",
                type: "POST",
                data: updateModel,
                success: res => {
                    if (!res.success) alert("更新失败:" + res.message);
                },
                error: () => alert("更新请求出错")
            });
        }

        // 新增行操作(可绑定到工具栏按钮或自定义按钮)
        function addNewRow() {
            const spreadsheet = $("#DataExcel").data("kendoSpreadsheet");
            const sheet = spreadsheet.activeSheet();
            const lastRow = sheet.usedRange().bottom;

            // 在最后一行插入新行
            sheet.insertRow(lastRow + 1, 1);
            // 设置新行样式
            sheet.range(lastRow + 1, 0, 1, 3)
                .verticalAlign("center")
                .color("black");
            sheet.range(lastRow + 1, 2, 1, 1).bold(true);
        }

        // 删除行操作(可绑定到工具栏按钮或右键菜单)
        function deleteSelectedRow() {
            const spreadsheet = $("#DataExcel").data("kendoSpreadsheet");
            const sheet = spreadsheet.activeSheet();
            const selectedRange = sheet.selectedRange();
            const rowIndex = selectedRange.top;

            // 禁止删除表头行
            if (rowIndex < 2) {
                alert("无法删除表头行");
                return;
            }

            const rowId = sheet.range(rowIndex, 0).value();
            // 未保存的新增行直接删除
            if (!rowId) {
                sheet.deleteRow(rowIndex, 1);
                return;
            }

            if (confirm("确定删除该行数据?")) {
                $.ajax({
                    url: "@Url.Action("DeleteData")",
                    type: "POST",
                    data: { id: rowId },
                    success: res => {
                        if (res.success) {
                            sheet.deleteRow(rowIndex, 1);
                        } else {
                            alert("删除失败:" + res.message);
                        }
                    },
                    error: () => alert("删除请求出错")
                });
            }
        }

        // 原选择事件逻辑保留
        function onSelect(e) {
            // 原有业务逻辑写在这里
        }
    </script>
}

3. 方案优势

  • 性能提升:客户端批量写入数据避免了服务器端循环生成大量DOM节点,数据量越大性能提升越明显。
  • 表头安全:预定义的复杂合并表头不会被数据覆盖,完全保留自定义结构。
  • 完整操作闭环:通过客户端事件和AJAX交互,实现了数据的增删改功能,配合Kendo Spreadsheet的原生API简化了行操作逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:55:00