Kendo Grid滚动到选定行

10

我希望能够调用一个函数,使Kendo表格滚动到选定的行。我已经尝试了一些方法,但是没有一种方法起作用,

例如我尝试了这个:

var grid = $("#Grid").data("kendoGrid"),
    content = $(".k-grid-content");
content.scrollTop(grid.select());

我也尝试了这个:

var gr = $("#Grid").data("kendoGrid");
var dataItem = gr.dataSource.view()[gr.select().closest("tr").index()];
var material = dataItem.id;
var row = grid.tbody.find(">tr:not(.k-grouping-row)").filter(function (i) {
    return (this.dataset.id == material);
});
content.scrollTop(row);

请问有人能指导我吗? :)

--- 编辑 ---

由于其他原因我无法绑定到更改事件,所以我必须能够调用一个函数来将列表滚动到所选行。这是我使用@Antonis为我提供的答案尝试过的方法。

var grid = $("#Grid").data("kendoGrid")
grid.element.find(".k-grid-content").animate({  
    scrollTop: this.select().offset().top  
 }, 400);

我尝试了一下,它确实将列表向下滚动了一些,但没有滚动到所选行。我是不是在错误地使用网格对象并调用了scrollTop方法?

还有这个:

var grid = $("#ItemGrid").data("kendoGrid");
grid.scrollToSelectedRow = function () {
    var selectedRow = this.select();
    if (!selectedRow) {    
        return false;    
    }
    this.element.find(".k-grid-content").animate({
        scrollTop: selectedRow.offset().top  
    }, 400);
    return true;
    };

grid.scrollToSelectedRow();

1
scrollTop() 接受一个整数参数,表示距离顶部的像素偏移量,而不是要滚动到的元素。例如,.scrollTop(0) 将滚动到顶部(距离顶部的像素偏移为 0)。 - CodingWithSpike
6个回答

16

所以这里大多数答案都犯了两个错误,一个是效率问题,另一个是实际的 bug。

  1. 使用 element.find(".k-grid-content")。这是极其不必要的。 grid.content 可以更轻松地(而且更快速地)给你相同的内容。

  2. 使用 .offset() 来查找行的位置。 这是不正确的: 这将告诉您该行相对于文档本身的位置。如果您的页面允许您滚动整个页面(而不仅仅是网格),则此数字将不正确。

    而是使用 .position() - 这会给你相对于偏移父级的位置。为了使 .position() 给出正确的结果,你的 grid.content 中的表格必须具有 position: relative 属性。 最好通过 CSS 样式表应用它:

    .k-grid-content table {
      position: relative;
    }

无论如何,假设你已经有了对网格本身的引用,我将称其为 grid,并且你已经将你的内容窗格设置为 relative 位置,那么你所要做的就是这样:

grid.content.scrollTop(grid.select().position().top);

或者,针对动画效果,

grid.content.animate({ scrollTop: grid.select().position().top }, 400);

正如之前讨论的,grid.content会得到内容面板,也就是您要滚动的部分。它是一个jQuery对象。

jQuery对象有一个.scrollTop方法,所以这部分非常简单。当您使用其scrollTop属性时,.animate方法的工作方式类似。现在我们只需要知道滚动到哪里。

为此,grid.select()返回一个jQuery对象,对应于所选行。那就是你想要滚动到的地方。为了获取其位置,我们使用jQuery的.position()方法。返回值是一个带有topleft字段的对象;我们想要滚动到其垂直位置,因此我们使用top

当然,在change回调中使用最容易;在那里,grid就是this(因为回调是在网格本身上调用的),当选择更改时,change会自动调用。但您可以随时调用此代码来滚动到所选项;您可以通过使用以下方式获得grid

grid = $('#theGridsId').data('kendoGrid');

应该是 grid.content.animate 吗? - AstroSharp
@AstroSharp:是的,我已经编辑了答案。等待同行审查。 - damd
这在单独使用onDataBound时非常有效,但是当我将其放入kendo tabstrip中时,在onDatabound中位置的值始终为零,并且只有在到达其相应选项卡时才能在onChange中正常工作。有什么想法吗? - SomeRandomDeveloper

6
当选择一行时,您可以自动完成此操作。将函数绑定到“change”事件,在其中,您可以滚动到所选行。(假设您只能选择一行,这由“this.select()”给出) JSFiddle示例 “更改”处理程序
//    bind to 'change' event
function onChangeSelection(e) {

    //    animate our scroll
    this.element.find(".k-grid-content").animate({  // use $('html, body') if you want to scroll the body and not the k-grid-content div
        scrollTop: this.select().offset().top  //  scroll to the selected row given by 'this.select()'
     }, 400);
}

1
我做了一个按钮,每当你点击它时调用滚动函数 --> http://jsfiddle.net/blackjim/9GCYE/12/ 滚动有一个小问题。试着在 scrollToSelectedRow 函数中用调试器修复它。不幸的是,我现在没有太多时间来修复它。 - AntouanK
谢谢你提供的示例代码,我在 jsfiddle 中测试了一下,发现它可以正常运行。我已经按照你的示例实现了新的网格滚动功能,虽然没有报错,但是还无法滚动。我对示例中最后一行的 "kendoScroller" 有些疑惑,因为我的编译器无法将其识别为已知函数。这是否是滚动条正常工作所必需的属性? - gardarvalur
我不记得我是否写过这行代码。也许我当时在尝试什么,然后忘记了它。 - AntouanK
element.find(".k-grid-content") 这种写法效率极低,建议使用 .content 代替。 - KRyan
此外,使用.offset()是完全错误的;那不是你想要的数字。.position()才是你想要的,但只有在你将position: relative;应用于grid.content(或通过CSS应用于.k-grid-content)时才是如此。 - KRyan
显示剩余5条评论

0

我在偏移方面遇到了问题,所以位置对我来说更好:

grid.element.find(".k-grid-content").animate({  // use $('html, body') if you want to scroll the body and not the k-grid-content div
                    scrollTop: this.select().position().top  //  scroll to the selected row given by 'this.select()'
                 }, 400);    

1
使用 element.content 代替 element.find(".k-grid-content"),后者效率极低。 - KRyan

0
这是更新后的代码
http://jsfiddle.net/27Phm/12/
//    bind to 'change' event
function onChangeSelection(e) {
    try {
        var $trSelect = this.select();
        var $kcontent = this.element.find(".k-grid-content");
        if ($trSelect && $trSelect.length == 1 && $kcontent) {
            var scrollContentOffset = this.element.find("tbody").offset().top;
            var selectContentOffset = $trSelect.offset().top;
            var IsMove = false;
            var distance = selectContentOffset - scrollContentOffset;
            distance += $kcontent.offset().top;
            if ($trSelect.prev().length == 1 && distance > $trSelect.prev().offset().top) {
                distance = (distance - $trSelect.prev().offset().top); //+ ($trSelect.height());
                //var toprows = $kcontent.scrollTop() / $trSelect.height(); //top rows above the scroll
                var selrowtotal = ($trSelect.offset().top - $kcontent.offset().top) + $trSelect.height();
                IsMove = selrowtotal > $kcontent.height() ? true : false;
                if (IsMove) $kcontent.scrollTop(distance);
            }
            if (!IsMove && $trSelect.offset().top < $kcontent.offset().top) {
                distance = selectContentOffset - scrollContentOffset;
                $kcontent.scrollTop(distance - 15);`enter code here`
            }
        }
    } catch (e) {

    }
}

看起来这行代码:if (IsMove) $kcontent.scrollTop(distance); 应该改为:if (IsMove) $kcontent.scrollTop(selrowtotal - distance); - CharlesC
1
这个问题可以并且应该用一行代码解决,如果你想非常清楚地表达你的意思,可以用两行代码。 - KRyan

0
我在Kendo移动MVVM中找到了一个函数来实现这个功能。
parent.set('onShow', function (e) {
   e.view.scroller.reset();
}

或者

app.xxx = kendo.observable({
   onShow: function() { e.view.scroller.reset(); }
});

0
除了之前提到的,如果你使用虚拟滚动,例如JQuery:
$("#grid").kendoGrid({
scrollable: {
    virtual: true
}});

或者在ASP.NET MVC中

.Scrollable(scrollable => scrollable.Virtual(true))

在这种情况下,看起来kendo为滚动条添加了一个特殊的div,位于右侧,类名为.k-scrollbar。因此,我们可以使用类似以下代码来滚动到所选行,而不是像之前提到的那样使用element.find(".k-grid-content").scrollTop(distance)grid.content.scrollTop(distance)

const myGrid = $("#myGrid");
const scrollContentOffset = myGrid.find("tbody").offset().top;
const selectContentOffset = myGrid.select().offset().top;
const distance = selectContentOffset - scrollContentOffset;
myGrid.find(".k-scrollbar").scrollTop(distance);

我在这方面有些困难,也许可以帮助别人节省一些时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接