可滚动 GridView






4.50/5 (2投票s)
跨浏览器支持可滚动的 GridView。
引言
本文提供了一个简单的、可重用的、跨浏览器的可滚动 GridView,它在一个 Web 用户控件中,可以与任何数据源一起使用。
背景
网页上显示的最常见信息之一是来自数据库的信息。而用于在浏览器中显示数据库信息的最常见的 Web 控件是 DataGrid
和 GridView
。然而,这些控件不提供任何滚动功能。因此,如果信息行数超过了浏览器一页的显示容量,用户就必须滚动页面才能看到所有数据,或者使用分页。分页不是个坏主意,除非访问者希望下载所有内容。
为 GridView 添加滚动功能的一种常用方法是将 GridView
声明包装在 HTML DIV
标签中。这样做时,GridView
的标题会随着显示的所有信息一起滚动。要解决这个问题,许多开发人员会隐藏 GridView
中的标题值,然后在 GridView
上方添加一个单独的表来显示列标题。这种方法在 IE 浏览器中效果很好,但在基于 Mozilla 的浏览器中,表的水平渲染方式不同。因此,开发人员必须对标题表进行繁琐的调整,才能在所有浏览器中使表和 GridView
正确对齐。此外,如果数据因应用程序规范的更改而发生变化,开发人员必须单独手动更改标题表。本文介绍了一个简单的 Web 用户控件,用于显示带有滚动条的信息行。
使用代码
要求
- Visual Studio 2005
- 例如 SQL Server 2005 Express 这样的数据库
- Internet Information Services 6.0
示例
要求应用程序开发人员在一个网页上显示客户联系人列表。该列表包含国内和国际客户。
数据库架构如下所示
网页上需要的字段是
- Name
- 邮政编码
- Street Address
- 电子邮件地址
- 城市
- 电话号码和分机号(如果提供)
- 州或国家
- 名字
- 姓氏
数据库中一次客户数不超过 2000。使用公共表表达式和 Union
语句将国内地址和国际地址合并成一个记录集。然后,使用一个不带输入参数的存储过程返回所有客户列表。
应用程序开发人员有时会这样编写他们的 Select
语句
'Using a common table expression to combine the domestic and international addresses
With Addresses as (
select DomesticAddressID as D_ID, 0 as I_ID, StAddress,
City, State, PostalCode from DomesticAddresses
Union
Select 0 as D_ID, InternationaAddressID as I_ID, StAddress,
City, Country as [State], PostalCode from InternationalAddresses
)
'retrieving the columns from the three tables - customers, Contact Information and Addresses
Select * From Customers c Inner Join ContactInformation ci on
c.ContactInformationID = ci.ContactInformation
Inner Join addresses on
c.DomesticAddress = addresses.D_ID and
c.internationalAddress = addresses.I_ID
注意:当客户是国内客户时,InternationalAddressID
的默认值为 0;当客户是国际客户时,则相反。
然后在 VB 代码中,将适当的列标题添加到已分离的表中,并删除非必需的列。
更好的方法是将所有适当的列名包含在存储过程中。如下所示
With Addresses as (
select DomesticAddressID as D_ID, 0 as I_ID, StAddress as [Street Address],
City, State as [Country or State], PostalCode as [Postal Code]
from DomesticAddresses
Union
Select 0 as D_ID, InternationaAddressID as I_ID, StAddress as [Street Address],
City, Country as [Country or State],
PostalCode as [Postal Code] from InternationalAddresses
)
Select Name, a.[Street Address], a.City, a.[Country or State], a.[Postal Code],
ci.email as [Email Address], ci.phone as [Phone Number],
ISNULL(ci.extension '') AS Extension,
ci.fname as [First Name], ci.lname as [Last Name]
From
Customers c Inner Join ContactInformation
ci on c.ContactInformationID = ci.ContactInformationID
Inner Join addresses a on c.DomesticAddressID = a.D_ID and
c.internationalAddressID = a.I_ID
当 T-SQL 中一切都拼写出来时,可以轻松地根据需求的变化添加/删除字段,而无需更改任何 Visual Basic 代码。
有了这个存储过程,VB 代码中唯一的要求就是在一个命令对象中执行存储过程,并将返回的记录集绑定到 GridView
。
Web 用户控件
下面是用户控件的图片。它有两个 GridView
,一个标题 GridView
和一个正文 GridView
。标题 GridView
不包含任何数据行。其唯一目的是显示列标题文本。正文 GridView
显示数据行;ShowHeaderRow
属性的值为 False
,RowStyle
TextWrap
属性为 True
。正文 GridView
包含在一个 div
容器中。div
标签的样式在样式表部分中描述。
代码隐藏类提供子例程来设置标题 GridView
,并设置标题 GridView
和正文 GridView
的列宽。
成员名称 |
成员类型 |
数据类型 或返回类型 |
参数 (名称:类型) |
访问级别 |
其他修饰符 |
|
variable |
|
|
||
|
variable |
|
|
||
|
属性 |
|
|
||
|
属性 |
|
|
||
|
子例程 |
不适用 |
不适用 |
|
|
|
子例程 |
不适用 |
不适用 |
|
|
|
子例程 |
不适用 |
不适用 |
|
|
|
子例程 |
不适用 |
ds:数据集引用 |
|
|
|
子例程 |
不适用 |
ds:数据集引用 |
|
<%@ Control Language="vb" AutoEventWireup="false"
CodeBehind="ScrollingGridView.ascx.vb" Inherits="YourNamespace.ScrollingGridView" %>
<asp:GridView ID="GVHeader" runat="server" ForeColor="Black">
</asp:GridView>
<div id="AdjResultsDiv" style="WIDTH: 610px; HEIGHT: 200px">
<asp:GridView ID="GVBody" runat="server" ShowHeader="False" ForeColor="Black">
</asp:GridView>
</div>
Public Partial Class ScrollingGridView _
Inherits System.Web.UI.UserControl
#Region "Private members"
Private _Recordset As DataSet
Private _ColWidths As New ArrayList
#End Region
#Region "Properties"
''' <summary> Sets the private member _recordset value. </summary>
''' <value> A Dataset object.</value>
''' <returns> a Dataset object.</returns>
Public Property Recordset() As DataSet
Get
Return _Recordset
End Get
Set(ByVal value As DataSet)
_Recordset = value
End Set
End Property
''' This property exposes an arraylist that sets
''' the width of the columns in the gridview.
''' The arraylist length must equal the number
''' of fields in the recordset. When no arraylist is
''' provided the default widths for each column is applied.
''' <summary> Sets the width of columns when
''' the default values are inappropriate. </summary>
''' <value> Each element in the arraylist represents
''' a column width (pixels) in the gridview.</value>
''' <returns>An Arraylist</returns>
''' <remarks>.</remarks>
Public Property ColWidths() As ArrayList
Get
Return _ColWidths
End Get
Set(ByVal value As ArrayList)
_ColWidths = value
End Set
End Property
#End Region
#Region "Page Events"
''' <summary> When the user control loads into the browser for the first time,
''' bind the DataGridview to the recordset property. Then, remove
''' all of the rows from the recordset, add an empty row and bind
''' the HeaderGridview to the recordset. </summary>
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
' When the page loads for the first time bind the gridviews to the recordset.
If Not Me.IsPostback
Me.GVData.DataSource = Me._Recordset
Me.GVData.DataBind()
' remove all of the rows from the recordset
' before binding to the header gridview.
Me.RemoveRows(_Recordset)
' Add an empty row to the recordset and bind to the HeaderGridview..
Me.AddHeaderRow(_Recordset)
End if
End Sub
''' <summary> Sets the column widths for the header. </summary>
''' <remarks>The gridview cell index is equal to the _ColWidths index. </remarks>
Public Sub HRowDataBound(ByVal sender As Object, _
ByVal e As GridViewRowEventArgs) Handles GVHeader.RowDataBound
If e.Row.RowType = DataControlRowType.Header Then 'search for a header row
Dim i As Integer ' arraylist counter
' Set the width of the cells in the header row equal to the colWidth values.
For i = 0 To _ColWidths.Count - 1
e.Row.Cells(i).Width = System.Web.UI.WebControls.Unit.Pixel(_ColWidths(i))
Next
End If
End Sub
''' <summary> Sets the column widths for the data. </summary>
''' <remarks>The column index is equal to the _ColWidths index. </remarks>
Public Sub DRowDataBound(ByVal sender As Object, _
ByVal e As GridViewRowEventArgs) Handles GVBody.RowDataBound
If e.Row.RowType <> DataControlRowType.Header Then ' search for data rows
Dim i As Integer ' arraylist counter
' Set the width of the cells in the header row equal to the colWidth values.
For i = 0 To _ColWidths.Count - 1
e.Row.Cells(i).Width = System.Web.UI.WebControls.Unit.Pixel(_ColWidths(i))
Next
End If
End Sub
#End Region
#Region "Subroutines"
''' <summary> Removes all rows from the input dataset. </summary>
''' <param name="ds">Dataset with rows in it.</param>
Private Sub RemoveRows(ByRef ds As DataSet)
ds.Tables(0).Rows.Clear()
End Sub
''' <summary> By default a gridview is hidden when there are no rows of data.
''' So, an empty row is added to the header gridview.. </summary>
''' <param name="ds">An empty dataset</param>
Private Sub AddHeaderRow(ByRef ds As DataSet)
Dim rcount As Integer = ds.Tables(0).Rows.Count ' store number of rows
If (rcount = 0) Then
' add a new row.
ds.Tables(0).Rows.Add(ds.Tables(0).NewRow())
' sets the datasource
Me.GVHeader.DataSource = ds.Tables(0)
' binds the datasource
Me.GVHeader.DataBind()
'store the number of columns.
Dim colCount As Integer = Me.GVHeader.Rows(0).Cells.Count
' remove any text from the cells
Me.GVHeader.Rows(0).Cells.Clear()
Me.GVHeader.Rows(0).Cells.Add(New TableCell()) ' add a new cell
'make the cell span across entire table
Me.GVHeader.Rows(0).Cells(0).ColumnSpan = colCount
Me.GVHeader.Rows(0).Cells(0).Text = String.Empty ' set the text value
End If
End Sub
#End Region
这是样式表语法
/* Scrolling gridview */
div#AdjResultsDiv {
width: 1080px;
height: 500px;
overflow: scroll;
position: relative;
}
div#AdjResultsDiv th
{
background-color:Navy;
cursor: default;
top: expression(document.getElementById("AdjResultsDiv").scrollTop-2);
left: expression(parentNode.parentNode.parentNode.parentNode.scrollLeft);
position: relative;
z-index: 20;
color:white;
}
div#AdjResultsDiv tbody
{
margin:auto;
}
这是在 ASPX 文件中的实现方式
要使用此控件,请在 Visual Studio 中创建一个新的 Web 窗体(ASPX 文件)。将 Web 用户控件添加到页面。然后,将样式元素添加到新的或现有的样式表中。
Web Form
表示文件包含 Web 用户控件,代码隐藏文件包含检索数据集并填充 Web 用户控件公共属性:RecordSet
和 ColWidths
的子例程。
成员名称 |
成员类型 |
数据类型 或返回类型 |
参数 (名称:类型) |
访问级别 |
其他修饰符 |
|
function |
|
不适用 |
|
|
|
子例程 |
不适用 |
不适用 |
|
Web 窗体 ASPX 文件
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="TestScrollGrid.aspx.vb"
Inherits="YourNamespace.TestScrollGrid" %>
<%@ Register Src="UserControls/ScrollingGridView.ascx"
TagName="ScrollingGridView" TagPrefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="TestScrollGrid" runat="server">
<div>
<uc1:ScrollingGridView ID="ScrollingGridViewSample" runat="server" />
</div>
</form>
</body>
</html>
代码隐藏文件
Partial Public Class TestScrollGrid _
Inherits System.Web.UI.Page
''' <summary> When the page loads into the browser for the first ti
''' retrieve the data into a dataset, set the user control recordset
''' property equal to the retrieved dataset, and assign values to the
''' user control colwidths arraylist.
'''</summary>
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
' get some data from the database.
If Not Me.IsPostBack Then
Dim ds As DataSet
Dim colwidths As New ArrayList
Try
ds = getdata()
Me.ScrollingGridViewSample.Recordset = ds
' add the width of each datarow column.
colwidths.Add(100)
colwidths.Add(500)
Me.ScrollingGridViewSample.ColWidths = colwidths
Catch ex as Exception
'evaluate the error message and display a user friendly message.
Finally
' clean up.
ds = Nothing
colwidths = Nothing
End Try
End If
End Sub
''' <summary> Retrieves data from a database. </summary>
''' <returns> Dataset</returns>
Private Function GetData() As DataSet
' Best practices frowns on writing database commands in a codebehind file.
' The code below is for demonstration purposes.
Dim connString as string = _
"data source=SQLServerName; initial catalog=DatabaseName;" & _
" persist security info=False; user id=UserID; password= password;"
'set up the sql connection.
Dim con As SqlClient.SqlConnection = New SqlConnection(ConnString)
con.Open()
Dim cmd As New SqlCommand("dbo.StoredProcName", con)
cmd.CommandType = CommandType.StoredProcedure
Dim ds as new dataset
Dim da As New SqlClient.SqlDataAdapter
Try
da.SelectCommand = cmd
da.Fill(ds)
GetData =ds
Finally
cmd = Nothing
da = Nothing
con.Close()
con = Nothing
End Try
End Function
End Class
就是这样!