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

跨页面同步Kendo Grid选中行需求及实现方案咨询

需求与解决方案

需求说明

  • 仪表板页面的Kendo Grid选中某一行时,跳转至工单页面,并自动选中该页面Kendo Grid内对应的行以展示工单详情
  • 若直接通过导航栏进入工单页面,则默认选中该页面Kendo Grid的第一行

现有代码

仪表板页面Kendo Grid代码

@(Html.Kendo().Grid<TP.Objects.Entities.Generic.Ticket>()
    .Name("ClientOpenTicketsDashboard")
    .Columns(columns =>
    {
        columns.Bound(c => c.Subject).Width("33.3%");
        columns.Bound(c => c.Message).Width("33.3%");
        columns.Bound(c => c.ExpectedSLA).Width("33.3%").ClientTemplate("#= kendo.toString(ExpectedSLA, 'MM/dd/yyyy') #");
    })
    .Selectable(x => x.Enabled(true))
    .Events(events => events.Change("TP.ClientSite.Banking.Banking.Onchange"))
    .Pageable(p => p.ButtonCount(2))
    .DataSource(dataSource => dataSource
    .Custom()
    .PageSize(5)
    .ServerPaging(true)
    .Transport(transport => transport
    .Read(read => read.TPApiUrl("/Ticketing/TicketApi/GetClientOpenTicketsPaged")
    .Data("GetUserID"))
    )
    .Schema(schema => schema
    .Data("Data")
    .Total("Total")
    .Errors("Errors")
    .Model(m => m.Id("TicketID"))
    )
    )
    .Deferred(false)
    )

工单页面Kendo Grid代码

@(Html.Kendo().Grid<TP.Objects.Entities.Generic.Ticket>()
    .Name("ClientOpenTicketsTicketPage")
    .Columns(columns =>
    {
        columns.Bound(c => c.Message).Width("100%").ClientTemplate(
        "<div><strong>Name:</strong></div>" +
        "<div>#= Message #</div>" +
        "<div>" +
        "<span class='status-background'><strong></strong> #= TicketStatus.Description #</span> " +
        "<span class='" +
        "# if (TicketPriority.Description == 'Low') { #" +
        "priority-low" +
        "# } else if (TicketPriority.Description == 'Medium') { #" +
        "priority-medium" +
        "# } else if (TicketPriority.Description == 'High') { #" +
        "priority-high" +
        "# } else if (TicketPriority.Description == 'Urgent') { #" +
        "priority-urgent" +
        "# } #" +
        "'><strong></strong> #= TicketPriority.Description #</span>" +
        "</div>"
        ).HtmlAttributes(new { @class = "left-align" });
    })
    .Selectable(x => x.Enabled(true))
    .Events(events =>
    {
        events.Change("TP.ClientSite.Banking.Banking.OnchangeForClientOpenTickets");
        events.DataBound("onDataBoundForClientOpenGrid");
    })
    .DataSource(dataSource => dataSource
    .Custom()
    .PageSize(1000)
    .ServerPaging(true)
    .Transport(transport => transport
    .Read(read => read.TPApiUrl("/Ticketing/TicketApi/GetClientOpenTicketsPaged")
    .Data("GetUserID"))
    )
    .Schema(schema => schema
    .Data("Data")
    .Total("Total")
    .Errors("Errors")
    .Model(m => m.Id("TicketID"))
    )
    )
    .Deferred(true)
    )

<script type="text/javascript">
    function onDataBoundForClientOpenGrid(e) {
        var grid = $("#ClientOpenTicketsTicketPage").data("kendoGrid");
        grid.tbody.find(">tr").addClass("custom-row-gap");
        var firstRow = grid.tbody.find(">tr").first();
        grid.select(firstRow);
        firstRow.trigger("click");
    }
</script>

工单页面选中事件及后端代码

// 处理ClientOpenTicketsTicketPage网格选中事件
module.OnchangeForClientOpenTickets = function (e) {
    var grid = $("#ClientOpenTicketsTicketPage").data("kendoGrid");
    var selectedItem = grid.dataItem(grid.select());
    var TicketID = selectedItem.TicketID;
    loadTicketMessages(TicketID);
    loadTicketDetails(TicketID);
};

// 根据TicketID加载工单消息
function loadTicketMessages(TicketID) {
    $.ajax({
        type: "GET",
        url: "/Ticket/Ticket/DisplayTicketMessages",
        data: { TicketID: TicketID },
        success: function (data) {
            $('#ticketMessageContainer').html(data);
        }
    });
}

// 根据TicketID加载工单详情
function loadTicketDetails(TicketID) {
    $.ajax({
        type: "GET",
        url: "/Ticket/Ticket/DisplayTicketDetails",
        data: { TicketID: TicketID },
        success: function (data) {
            $('#ticketDetailsContainer').html(data);
        }
    });
}
public async Task<IActionResult> DisplayTicketDetails(Guid TicketID)
{
    OverviewTicketSystemModel vm = new OverviewTicketSystemModel();

    vm.Ticket = await _TicketApiClient.GetTicketByIDAsync(TicketID);

    return PartialView("Partials/_TicketDetailsPartial", vm);
}

public async Task<IActionResult> DisplayTicketMessages(Guid TicketID)
{
    OverviewTicketSystemModel vm = new OverviewTicketSystemModel();

    vm.Ticket = await _TicketApiClient.GetTicketByIDAsync(TicketID);

    return PartialView("Partials/_TicketMessagesPartial", vm);
}

解决方案

1. 修改仪表板页面的选中事件

在仪表板的TP.ClientSite.Banking.Banking.Onchange函数中,获取选中行的TicketID并携带参数跳转至工单页面:

TP.ClientSite.Banking.Banking.Onchange = function(e) {
    var grid = $("#ClientOpenTicketsDashboard").data("kendoGrid");
    var selectedItem = grid.dataItem(grid.select());
    if (selectedItem) {
        // 替换为实际工单页面路由
        window.location.href = "/Ticket/Ticket/Index?TicketID=" + selectedItem.TicketID;
    }
};

2. 修改工单页面的DataBound事件

更新onDataBoundForClientOpenGrid函数,通过URL参数判断来源,实现对应行选中逻辑:

function onDataBoundForClientOpenGrid(e) {
    var grid = $("#ClientOpenTicketsTicketPage").data("kendoGrid");
    grid.tbody.find(">tr").addClass("custom-row-gap");
    
    // 从URL获取目标TicketID
    const urlParams = new URLSearchParams(window.location.search);
    const targetTicketID = urlParams.get('TicketID');
    
    if (targetTicketID) {
        // 查找对应TicketID的行
        const targetDataItem = grid.dataSource.get(targetTicketID);
        if (targetDataItem) {
            var targetRow = grid.tbody.find(`tr[data-uid="${targetDataItem.uid}"]`);
            if (targetRow.length > 0) {
                grid.select(targetRow);
                targetRow.trigger("click");
                // 滚动到目标行
                grid.element.scrollTop(targetRow.offset().top - grid.element.offset().top);
                return;
            }
        }
    }
    // 无目标ID或未找到时,选中第一行
    var firstRow = grid.tbody.find(">tr").first();
    if (firstRow.length > 0) {
        grid.select(firstRow);
        firstRow.trigger("click");
    }
}

3. 分页场景适配(可选)

如果工单页面启用分页且PageSize不是1000,需遍历页面查找目标行:

// 分页场景下定位目标行
function locateTicketInPagedGrid(grid, targetTicketID) {
    var dataSource = grid.dataSource;
    var totalPages = dataSource.totalPages();
    
    function checkPage(page) {
        dataSource.page(page).then(function() {
            const targetDataItem = dataSource.get(targetTicketID);
            if (targetDataItem) {
                var targetRow = grid.tbody.find(`tr[data-uid="${targetDataItem.uid}"]`);
                if (targetRow.length > 0) {
                    grid.select(targetRow);
                    targetRow.trigger("click");
                    grid.element.scrollTop(targetRow.offset().top - grid.element.offset().top);
                    return;
                }
            }
            if (page < totalPages) {
                checkPage(page + 1);
            } else {
                // 遍历完未找到,选中第一行
                var firstRow = grid.tbody.find(">tr").first();
                if (firstRow.length > 0) {
                    grid.select(firstRow);
                    firstRow.trigger("click");
                }
            }
        });
    }
    
    checkPage(1);
}

// 在DataBound中替换为该函数(需分页时使用)
// if (targetTicketID) {
//     locateTicketInPagedGrid(grid, targetTicketID);
// } else {
//     var firstRow = grid.tbody.find(">tr").first();
//     if (firstRow.length > 0) {
//         grid.select(firstRow);
//         firstRow.trigger("click");
//     }
// }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 22:10:54