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

冻结窗格 DataGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.68/5 (59投票s)

2004年11月14日

CPOL

3分钟阅读

viewsIcon

884724

downloadIcon

11898

创建一个 DataGrid,能够锁定标题行和第一列。

Sample Image

引言

在最近的一个项目中,我被要求使 DataGrid 的行为类似于 Excel 的冻结窗格。没错,就是冻结标题行和 DataGrid 的左侧列。在花费数小时搜索已经完成并发布代码的人之后,我放弃并尝试自己找出解决方案。上面的项目源代码提供了三个 ASPX 文件。一个用于从客户端锁定列,一个用于从服务器端锁定列,还有一个用于从服务器端锁定列,然后从客户端解锁/锁定列。

背景

这个计划实际上相当简单。在网上搜索解决方案时,我发现一篇关于如何从 HTML 表格创建冻结窗格的精彩文章。该解决方案基于 CSS,仅适用于 Internet Explorer,但在其他浏览器中表现良好。我想感谢 Brett Merkey 提供的这个解决方案。他的“锁定或冻结带有非滚动标题的列”为我提供了灵感,可以在这里查看。

该解决方案非常简单,最终,您将有两种不同的方法来锁定 DataGrid 列。

以下是我们创建冻结窗格效果的概要

  • 创建一个简单的 DataGrid,其中的数据被 <div> 标签包围。
  • 修改 DataGrid 以在标题行中呈现 <th> 标签。
  • 创建一个样式表,该样式表将锁定 DataGrid 标题行和列。
  • 从客户端锁定列。
  • 从服务器端锁定列。

使用代码

修改 DataGrid 以呈现 <th> 标签

我们遇到的第一个问题是 DataGrid 不会呈现 <th> 元素,而是在标题中呈现常见的 <td> 元素。幸运的是,微软为此发布了一个相当模糊的修补程序。我们大多数人已经在不知不觉中下载了此修补程序。您可以这里查看更多信息(或者如果您尚未下载,请下载)。

除了其他内容外,此修补程序还为 DataGrid 添加了属性 UseAccessibleHeader。当此属性设置为 true 时,它将‘在带有 scope="col" 属性的 <th> 标签中呈现 DataGrid 表格标题。’

完成后的 DataGrid 代码将如下所示

<div id="div-datagrid">
<asp:DataGrid id="DataGrid1" runat="server" CssClass="Grid" UseAccessibleHeader="True">
    <AlternatingItemStyle CssClass="GridAltRow"></AlternatingItemStyle>
    <ItemStyle CssClass="GridRow"></ItemStyle>
    <Columns>
    <asp:BoundColumn DataField="Name" HeaderText="Name" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    <asp:BoundColumn DataField="Address" HeaderText="Address" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    <asp:BoundColumn DataField="City" HeaderText="City" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    <asp:BoundColumn DataField="State" HeaderText="State" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    <asp:BoundColumn DataField="Zip" HeaderText="Zip" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    <asp:BoundColumn DataField="Random Babble" 
        HeaderText="Random Babble" 
        ItemStyle-Wrap="False"></asp:BoundColumn>
    </Columns>
</asp:DataGrid>
</div>

创建样式表

样式表是该项目的关键。有两件事需要注意。首先,使用了 CSS 表达式。CSS 表达式在 Internet Explorer 5.0 中引入,它允许您将 JavaScript 表达式分配给 CSS 属性。在这种情况下,我们通过使用表达式来设置文档元素的水平和垂直滚动位置。其次,样式需要以一定的顺序设置。如果您更改下面列出的样式的顺序,您将得到一些相当奇怪的结果。如果您想知道...是的,我在实际想出一个有效的顺序之前,几乎尝试了每一个不正确的顺序。

这是 CSS 代码

/* Div container to wrap the datagrid */
div#div-datagrid {
width: 420px;
height: 200px;
overflow: auto;
scrollbar-base-color:#ffeaff;
}

/* Locks the left column */
td.locked, th.locked {
font-size: 14px;
font-weight: bold;
text-align: center;
background-color: navy;
color: white;
border-right: 1px solid silver;
position:relative;
cursor: default;
/*IE5+ only*/
left: expression(document.getElementById("div-datagrid").scrollLeft-2);
}

/* Locks table header */
th {
font-size: 14px;
font-weight: bold;
text-align: center;
background-color: navy;
color: white;
border-right: 1px solid silver;
position:relative;
cursor: default;
/*IE5+ only*/
top: expression(document.getElementById("div-datagrid").scrollTop-2);
z-index: 10;
}

/* Keeps the header as the top most item. Important for top left item*/
th.locked {z-index: 99;}

/* DataGrid Item and AlternatingItem Style*/
.GridRow {font-size: 10pt; color: black; font-family: Arial; 
             background-color:#ffffff; height:35px;}
.GridAltRow {font-size: 10pt; color: black; font-family: Arial; 
             background-color:#eeeeee; height:35px;}

从客户端锁定列

为了从客户端锁定列,我们只需要创建一个脚本,将第一列的样式更改为“locked”。只需修改下面的代码即可冻结多列。以下脚本已添加到 ASPX 文件的头部以锁定第一列。

function lockCol(tblID) {
  var table = document.getElementById(tblID);
  var button = document.getElementById('toggle');
  var cTR = table.getElementsByTagName('tr');  //collection of rows

  if (table.rows[0].cells[0].className == '') {
    for (i = 0; i < cTR.length; i++)
    {
    var tr = cTR.item(i);
    tr.cells[0].className = 'locked'
    }
    button.innerText = "Unlock First Column";
  } else {
    for (i = 0; i < cTR.length; i++)
        {
    var tr = cTR.item(i);
    tr.cells[0].className = ''
    }
    button.innerText = "Lock First Column";
  }
}

从服务器端锁定列

同样,为了从服务器端锁定列,我们只需要将第一列的样式更改为“locked”。为了实现这一点,我们使用 DataGridItemDataBound 方法。以下代码将第一列的样式设置为“locked”。这实际上非常简单,使用下面的代码

Sub Item_Bound(ByVal sender As Object, ByVal e As DataGridItemEventArgs) _
Handles DataGrid1.ItemDataBound
    e.Item.Cells(0).CssClass = "locked"
End Sub

并且冻结前两列也同样容易

Sub Item_Bound(ByVal sender As Object, ByVal e As DataGridItemEventArgs) _
Handles DataGrid1.ItemDataBound
    e.Item.Cells(0).CssClass = "locked"
    e.Item.Cells(1).CssClass = "locked"
End Sub
© . All rights reserved.