65.9K
CodeProject 正在变化。 阅读更多。
Home

如何冻结 Radgrid MVC 中的列

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (2投票s)

2011年5月3日

CPOL

3分钟阅读

viewsIcon

59919

downloadIcon

1026

介绍如何在 Telerik Radgrid MVC 中冻结列,该功能目前在该控件中不可用。

引言

本文的目的是在 RadGrid MVC 中冻结列。目前,RadGrid MVC 中没有此功能,因此我决定自己创建一个。本文演示了在滚动时使 RadGrid 列保持静态的功能。当用户使用水平滚动条导航时,您希望始终使部分列数据可见,这将非常有用。

Using the Code

要启用此网格功能,只需在客户端将控件的“freezeGridColumn”设置为一个值,该值决定了当您在网格中拖动水平滚动条时将保持静态定位的列数(从最左边的列开始)。

<script type="text/javascript">
    function applyFrozenColumns() {
        $('#CustomerGrid').freezeGridColumn(1);
    }
</script>
<div class="grid">
     <%
        Html.Telerik().Grid(Model)
            .Name("CustomerGrid")
            .Columns(columns => 
                     {
                         columns.Bound(c => c.Title).Width(80);
                         columns.Bound(c => c.FirstName).Width(280);
                         columns.Bound(c => c.LastName).Width(180);
                         columns.Bound(c => c.Address).Width(180);
                         columns.Bound(c => c.Suburb).Width(180);
                         columns.Bound(c => c.State).Width(180);
                         columns.Bound(c => c.Postcode).Width(180);
                         columns.Bound(c => c.Email).Width(180);
                         columns.Bound(c => c.Mobile).Width(180);
                         columns.Bound(c => c.Telephone).Width(180);
                         columns.Bound(c => c.Fax).Width(180);
                     })
        .Sortable(sorting => sorting.SortMode(GridSortMode.SingleColumn))
        .DataBinding(binding => binding.Ajax().Select("GetCustomers", "Home"))
        .Scrollable(scrolling => scrolling.Height(150)).Render();
    %>

    <% Html.Telerik().ScriptRegistrar().OnDocumentReady("applyFrozenColumns();"); %>
</div>

它是如何工作的?

为了实现冻结列,我们必须首先了解 Radgrid 的渲染方式、其整体结构和行为。如果您使用 Firebug 在 Firefox 中查看 HTML 源代码,您会发现 Radgrid 包含 3 个部分。

  1. 标题
  2. Content
  3. 页脚

source_code.gif

我们感兴趣的部分是 Header(页眉)和 Content(内容)。每个部分都包含一个定义网格布局的表。允许页眉和内容在滚动时链接在一起的网格内部锁定机制,仅仅是通过设置每个列的固定宽度来实现的。

如果我们查看内容部分,它使用样式来实现基本的滚动。内容部分包含一个具有固定宽度列的表。如果表超出了其父容器的固定宽度,它将按默认行为自动滚动。

现在我们理解了 Radgrid 滚动背后的基本机制,我们可以实现自己的功能来实现冻结列。以下步骤提供了高层设计以及其工作原理。

步骤 1

禁用内容容器中的默认滚动。为此,我们只需使用 jQuery 来操作内容容器的样式,将“overflow”设置为 hidden,以防止其滚动。

第二步

在内容容器之后插入一个自定义的冻结容器。在冻结容器内,插入一个子冻结容器。目的是创建我们自己的自定义滚动,以实现冻结列功能。父冻结容器将决定滚动多少,而子容器将决定内容容器内表的宽度。

source_code1.gif

步骤 3

确定有多少列隐藏在内容容器后面。完成此操作后,我们将为隐藏在内容容器后面的列设置滚动。这样做可以最大程度地降低性能成本。

screenshot5.gif

步骤 4

附加到滚动容器的滚动事件。当滚动事件触发时,这就是我们实现功能的地方。

步骤 5

确定当前滚动位置,然后相应地显示表头和表内容列。这是此功能的核心部分,我们检查当前滚动位置,如果它超出了显示列的宽度,则隐藏它,否则显示它。隐藏表格单元格的效果会产生一种滚动的感觉,但实际上只是单元格内部的单元格在隐藏。

技术详情

在 jQuery 中创建一个名为“FreezeGridColumn”的新函数,以启用冻结列功能。然后确定其绑定行为,无论是服务器绑定还是 Ajax 绑定。对于 Ajax 绑定,我们需要知道 Ajax 请求何时完成。否则,在渲染未完成时我们将获得错误的父宽度。

 $.fn.freezeGridColumn = function(frozenColumnsCount) {
        
    if (!$(this).data('tGrid').isAjax()) {
        initFreezeColumns($(this), frozenColumnsCount);
    }
    else {
        $(this).ajaxStop(function() {
            initFreezeColumns($(this), frozenColumnsCount);
        });
    }
}; 

在 RadGrid 中插入自定义滚动处理以实现冻结列功能。首先,我们需要通过将样式设置为“overflow hidden”来禁用默认滚动。其次,我们在下方创建冻结容器来处理自定义滚动。

 function createScrollContainer() {
        //disable grid default scrolling
        $(grid).find(".t-grid-content").css("overflow-x", "hidden");

        if ($(frozenContainer).length == 0) {
            //create controls to handle freeze column scrolling
            frozenContainer = $("<div id='gridfrozenContainer' />");
            frozenInnerContainer = $("<div id='gridfrozenInnerContainer' />");
        }

        $(frozenContainer).css("height", "17px").css("overflow", 
				"scroll").css("width", "100%");
        $(frozenInnerContainer).css("height", "17px").css("width", 
				$(gridContentTable).width());

        $(frozenContainer).append($(frozenInnerContainer));
        $(frozenContainer).insertAfter('.t-grid-content');
    } 

确定内容容器中有多少列不可见。

  //get how many columns are not visible behind the content container
    function getHiddenColCount() {
        var visibleWidth = grid.find("div.t-grid-header").width();
        var visibleColCount = 0;

        $.each(tableHeaderGroupCol, function(idx, value) {
            totalColWidth += getWidth($(value));

            if (visibleWidth >= totalColWidth) {
                visibleColCount = idx;
            }
        });

        hiddenColCount = totalColCount - visibleColCount;
    } 

执行冻结功能。

for (i = frozenColumnsCount; i <= hiddenColCount; i++) {
     totalColWidth += columnWidthArr[i - 1];

     var showCol = (scrollPos < totalColWidth);

     $(tableHeaderCol).eq(i).children().toggle(showCol);
     $(tableHeaderGroupCol).eq(i).toggle(showCol);
     $(tableContentGroupCol).eq(i).toggle(showCol);
     $(tableHeaderCol).eq(i).toggle(showCol);
     $(gridContentTable).find("tbody tr td[cellIndex=" + i + "]").toggle(showCol);    
}    

浏览器支持

  • 在 IE6、IE7、IE8、IE9、Chrome 和 Firefox 中测试

限制

  • 冻结列不支持与层次结构网格一起使用

屏幕截图

source_code3.gif

source_code2.gif

历史

  • 08/08/2011
    • 修复了 bug - 冻结多列时丢失列
  • 09/05/2011
    • 修复了最后一列显示不正确的问题
  • 05/05/2011
    • 支持浏览器 Internet Explorer 8、Internet Explorer 9
© . All rights reserved.