刷新后剑道网格单元重新聚焦

Posted

技术标签:

【中文标题】刷新后剑道网格单元重新聚焦【英文标题】:Kendo grid cell refocusing after refresh 【发布时间】:2014-05-07 17:31:08 【问题描述】:

我有一个可选择、可导航和可编辑的网格。在单元格中输入值后,我必须更改更新单元格下的单元格中的值。要显示两个单元格的更新值,我必须刷新网格。当我这样做时,编辑的单元格失去焦点。我找到了一种在保存事件期间重新聚焦最后编辑的单元格的方法:

save: function (e) 
    var focusedCellIndex = this.current()[0].cellIndex;    //gets the cell index of the currently focused cell

    //...some dataItem saving (dataItem.set()) logic...

    this.refresh();    //refreshing the grid instance

    setTimeout(function ()     //refocusing the cell
        return function () 
            var focusedCell = $("#grid tr[data-uid='" + dataItem.uid + "'] td:nth-child(" + (focusedCellIndex + 1) + ")");
            $('#grid').data('kendoGrid').editCell(focusedCell);
        
    (), 200);

问题是这是第一次工作,但如果我再次尝试重新编辑同一个单元格,单元格就会失去焦点。当我尝试调试时,似乎this.current()[0].cellIndex 在第二次尝试中返回 0,并且由于该单元格聚焦不再起作用。

有谁知道为什么this.current() 第一次工作,而不是第二次工作?还有其他方法可以重新聚焦单元格吗?

【问题讨论】:

【参考方案1】:

如果没有在演示中看到它,很难准确地说出正在发生的事情,所以如果可以的话,我建议创建一个用于说明。我猜对 refresh 的调用正在删除当前的单元格选择并关注第一个单元格,因为网格是可导航的(我不太明白这种行为背后的基本原理,但很难说这是否是一个错误,因为我们无法阅读 Telerik 的代码 cmets)。

一种可行的方法是修改current 方法以同时存储当前单元格索引:

kendo.ui.Grid.fn.refresh = (function(refresh) 
    return function(e) 
        this._refreshing = true;

        refresh.call(this, e);

        this._refreshing = false;
    
)(kendo.ui.Grid.fn.refresh);

kendo.ui.Grid.fn.current = (function(current) 
    return function(element) 
        // assuming element is td element, i.e. cell selection
        if (!this._refreshing && element) 
            this._lastFocusedCellIndex = $(element).index(); // note this might break with grouping cells etc, see grid.cellIndex() method
            this._lastFocusedUid = $(element).closest("tr").data("uid");
        

        return current.call(this, element);
    
)(kendo.ui.Grid.fn.current);

kendo.ui.Grid.fn.refocusLastEditedCell = function () 
    if (this._lastFocusedUid ) 
        var row = $(this.tbody).find("tr[data-uid='" + this._lastFocusedUid + "']");
        var cell = $(row).children().eq(this._lastFocusedCellIndex);
        this.editCell(cell);
    
;

这样,您应该始终能够在需要时使用grid.refocusLastEditedCell()

另一个想法:

save: function (e) 
    var focusedCell = this.current();
    var focusedCellIndex = focusedCell.index();    //gets the cell index of the currently focused cell

    //...some dataItem saving (dataItem.set()) logic...

    this.refresh();    //refreshing the grid instance

    // reset current cell..
    this.current(focusedCell);

    setTimeout(function ()     //refocusing the cell
        return function () 
            var focusedCell = $("#grid tr[data-uid='" + dataItem.uid + "'] td:nth-child(" + (focusedCellIndex + 1) + ")");
            $('#grid').data('kendoGrid').editCell(focusedCell);
        
    (), 200);

【讨论】:

谢谢,我认为我们正在使用第一种方法。 _lastFocusedCellIndex 现在一直在工作。但是,例如,如果我在第 3 行编辑单元格 10,它将重新聚焦;如果我再次编辑它,焦点将转到第 1 行的单元格 10。所以,我只需要获取最后一个焦点单元格行的 rowIndex(或 uid)。我尝试使用this._lastFocusedCell = $(element); 扩展您的kendo.ui.Grid.fn.current 版本,然后获取单元格的数据项,但第二次返回网格的第一个数据项。 您不应该使用对 DOM 元素的引用,因为它们会在网格刷新时被替换;我更新了我的答案 非常感谢,即使在 IE 中它也能正常工作 :) 我会为您所做的每条评论或回答 +1,但我还没有足够的声誉 :) 我想我可以因为网格刷新而忘记验证?我正在尝试在 dataSource 模型中进行经典和自定义验证,但似乎没有任何效果。 不确定我理解你在做什么;如果您调用 editCell(cell) 并希望记住该单元格,您也可以显式调用 current(cell)【参考方案2】:

我没有足够的声誉来评论答案,但我要感谢 Lars Hoppner 的回答。它极大地帮助了我解决 Kendo Grids 令人讨厌的刷新导航问题。

我还想为带有水平滚动条的网格添加这一点,您的解决方案仍会导致滚动尽可能向左移动,同时保持最后编辑的单元格处于视图中。为了防止这种不良行为,我做了以下事情:

grid.closeCell();
grid.refresh();
grid.refocusLastEditedCell();

在刷新之前关闭单元格使滚动条保持原位,现在一切正常。希望这可以帮助其他人查看您的答案。

【讨论】:

您还可以保存和恢复具有滚动条的 DOM 元素的 $.scrollTop 和 $.scrollLeft 值(.k-scrollbar-horizo​​ntal/vertical 用于常规滚动或 .k-virtual-使用虚拟滚动时可滚动换行) 我还没有尝试过,听起来它会起作用。我唯一担心的是用户可能会看到网格“闪烁”,因为它快速来回滚动。不过还没有确认。

以上是关于刷新后剑道网格单元重新聚焦的主要内容,如果未能解决你的问题,请参考以下文章

日期格式在重新加载剑道网格时重置

在 MVC 中重新绑定剑道网格

如何自动更新剑道网格?

刷新网格后剑道ui网格可分页大小发生变化

Kendo Grid 如何以编程方式聚焦网格单元并阻止选择文本

从另一个视图重新绑定剑道网格到以前的搜索条件的正确方法是啥(后退按钮不起作用)