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

可滚动 GridView

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (2投票s)

2010年4月6日

CPOL

4分钟阅读

viewsIcon

36177

downloadIcon

684

跨浏览器支持可滚动的 GridView。

引言

本文提供了一个简单的、可重用的、跨浏览器的可滚动 GridView,它在一个 Web 用户控件中,可以与任何数据源一起使用。

背景

网页上显示的最常见信息之一是来自数据库的信息。而用于在浏览器中显示数据库信息的最常见的 Web 控件是 DataGridGridView。然而,这些控件不提供任何滚动功能。因此,如果信息行数超过了浏览器一页的显示容量,用户就必须滚动页面才能看到所有数据,或者使用分页。分页不是个坏主意,除非访问者希望下载所有内容。

为 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 属性的值为 FalseRowStyle TextWrap 属性为 True。正文 GridView 包含在一个 div 容器中。div 标签的样式在样式表部分中描述。

代码隐藏类提供子例程来设置标题 GridView,并设置标题 GridView 和正文 GridView 的列宽。

成员名称

成员类型

数据类型

或返回类型

参数

(名称:类型)

访问级别

其他修饰符

_Recordset

variable

DataSet

Private

_ColWidths

variable

ArrayList

Private

Recordset

属性

DataSet

Public

ColWidths

属性

ArrayList

Public

Page_load

子例程

不适用

不适用

Protected

HRowDataBound

子例程

不适用

不适用

Public

Handles GVHeader.RowDataBound

BRowDataBound

子例程

不适用

不适用

Public

Handles GVBody.RowDataBound

RemoveRows

子例程

不适用

ds:数据集引用

Private

AddHeaderRow

子例程

不适用

ds:数据集引用

Private

Web 用户控件文件 ASCX
<%@ 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 用户控件公共属性:RecordSetColWidths 的子例程。

成员名称

成员类型

数据类型

或返回类型

参数

(名称:类型)

访问级别

其他修饰符

GetData

function

DataSet

不适用

Private

Page_Load

子例程

不适用

不适用

Protected

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

就是这样!

© . All rights reserved.