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

使用自定义分页在 ASP.NET GridView 控件中显示新闻文章列表

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.50/5 (2投票s)

2007年7月27日

CPOL

3分钟阅读

viewsIcon

43539

在具有自定义分页的 ASP.NET GridView 控件中显示新闻文章列表。

Screenshot - screenshot.jpg

引言

我正在开发一个网站,需要一种在 GridView 控件中显示新闻文章的方法,但允许一次分页浏览一定数量的文章,这样如果用户查看完整的存档,页面就不会太长。

GridView 控件中的默认分页效果不佳,因为它总是从数据库中检索所有记录,然后只显示您想要的记录。 我更希望只获取当前页面所需的记录,并让 SQL Server 完成所有工作,从而减少对 Web 应用程序的影响。

在网上搜索后,我找到了一些文章,但没有一个真正适合我,所以我决定自己编写一个。 顺便说一句,我首先在一张纸上画出逻辑,然后再深入研究代码,这确实有助于我集中注意力,并确保我没有浪费时间走错误的方向。 让我们开始编写代码...

使用代码

首先,我的 SQL 新闻文章表的结构如下

  • UniqueID
  • NewsCategory
  • DatePosted
  • 标题
  • 正文
  • 显示

UniqueID 是一个自动递增的标识列,Display 列是一个位(True/False)。

因此,除了分页之外,我还需要能够按 NewsCategory 过滤我的记录,以及搜索在 TitleBody 字段中找到的单词。 为此,我创建了一个存储过程,如下所示

CREATE PROCEDURE spGetNews
@iPageIndex INT,
@iMaxRows INT,
@iCategory INT,
@strSearch VARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;

DECLARE @iStart INT
SELECT @iStart = (@iPageIndex - 1) * @iMaxRows
DECLARE @iEnd INT
SELECT @iEnd = @iStart + @iMaxRows

IF OBJECT_ID (N'#TempNews',N'U') IS NOT NULL
DROP TABLE #TempNews

CREATE TABLE #TempNews(
intUniqueID INT PRIMARY KEY IDENTITY(1, 1),
dtPosted DATETIME,
strTitle VARCHAR(100),
strBody VARCHAR (5000),
strNewsCategory VARCHAR(50)
)

INSERT #TempNews 
SELECT N.dtPosted,
N.strTitle,
N.strBody, 
C.strNewsCategory 
FROM tblNews N 
INNER JOIN tblNewsCategory C ON
C.intUniqueID = N.intNewsCategory
WHERE
((@iCategory = 0) OR (intNewsCategory = @iCategory)) AND
((@strSearch = '') OR (strTitle LIKE '%' + @strSearch + '%')) OR
((@strSearch = '') OR (strBody LIKE '%' + @strSearch + '%')) AND
bitActive = 1 
ORDER BY dtPosted DESC

SELECT * FROM #TempNews
WHERE intUniqueID > @iStart
AND intUniqueID <= @iEnd

DROP TABLE #TempNews
END

我传递给过程的参数是

  • @iPageIndex
  • @iMaxRows
  • @iCategory
  • @strSearch

@PageIndex 指的是我们正在查看的当前结果页面。 @iMaxRows 指的是每页显示的记录数 - 请注意,它被称为最大行数,因为最后一页可能包含比其他页面少的记录,具体取决于记录总数。 @iCategory 指的是用于过滤结果的类别,并且是可选的。 @strSearch 指的是用于过滤结果的任何搜索词,也是可选的。

我们首先要做的是根据当前页面和要获取的记录数设置记录集的开始值和结束值。 我们稍后将使用这些值来仅选择相关的记录以传递回我们的 Web 应用程序。

接下来,我们创建一个带有自动递增标识列的临时表 - 这很重要,因为如果从我们的原始新闻文章表中删除记录,ID 将不再是连续的 - 但是,如果我们将记录插入到我们的临时表中,ID 将是连续的,我们可以在开始值和结束值之间进行选择。

然后,我们从新闻文章表中选择适当的记录,并将这些记录插入到我们的临时表中,最后,我们从临时表中选择 ID 介于开始值和结束值之间的结果。 选择它们后,我们从内存中删除我们的临时表。

所以现在,我们有了一个 SQL 存储过程,它将根据一些过滤和分页参数返回一组结果。 我们如何在 Web 应用程序中使用它?

这是我的 *News.aspx* 页面的源代码

<h3>Latest News</h3><br />
<div id="SiteNews" runat="server">
<asp:GridView ID="gvNews" runat="server" AutoGenerateColumns="False" 
  BorderColor="Black" BorderStyle="Solid" BorderWidth="1px" 
  GridLines="None" DataKeyNames="intUniqueID" Width="100%">
<Columns>
<asp:BoundField DataField="intUniqueID" Visible="False" />
<asp:BoundField DataField="dtPosted" 
  DataFormatString="{0:dd/MM/yyyy}" HtmlEncode="False" HeaderText="Posted">
<HeaderStyle HorizontalAlign="Center" Width="70px" />
<ItemStyle HorizontalAlign="Center" Width="70px" />
</asp:BoundField>
<asp:BoundField DataField="strNewsCategory" HeaderText="Category">
<HeaderStyle HorizontalAlign="Center" Width="80px" />
<ItemStyle HorizontalAlign="Center" Width="80px" />
</asp:BoundField>
<asp:BoundField DataField="strTitle" HeaderText="Article Title">
</asp:BoundField>
<asp:HyperLinkField Text="View Complete Atricle">
<HeaderStyle Width="100px" />
<ItemStyle HorizontalAlign="Right" Width="100px" />
</asp:HyperLinkField>
</Columns>
<HeaderStyle BackColor="#CCCCCC" />
<AlternatingRowStyle BackColor="#dbdbfe" />
</asp:GridView>
<div id="Pager" runat="server">&nbsp;</div>
</div>

请注意,我有两个 div,一个用于 GridView 控件,另一个名为 Pager,用于显示分页的页码。 (顺便说一句 - 检查 dtPosted 列,您会看到我指定了日期格式和 HtmlEncode - 如果 HtmlEncode 未设置为 false,则不会应用您的格式。)

现在我们有了网格,让我们在代码隐藏页中将数据绑定到它。

Page_Load 事件中,我调用以下例程

FillNewsGrid("News.aspx", gvNews, Pager, iMaxRows, 
             iCurrentPage, iCategory, txtSearchText.Value)

该例程如下所示

Private Sub FillNewsGrid(ByVal strPage As String, ByRef gvGrid As GridView, _
        ByRef divPager As HtmlGenericControl, ByVal iMaxRows As Integer, _
        Optional ByVal iCurrentPage As Integer = 1, _
        Optional ByVal iCategory As Integer = 0, _
        Optional ByVal strSearchText As String = "")
    If iCurrentPage = 0 Then iCurrentPage = 1

    Dim connSql As SqlConnection = New SqlConnection(strConnection)
    Dim cmdSql As SqlCommand = New SqlCommand
    cmdSql.Connection = connSql

    Dim iTotal As Integer = 0
    cmdSql.CommandText = "SELECT COUNT (*) FROM tblNews"
    connSql.Open()
    iTotal = cmdSql.ExecuteScalar
    connSql.Close()

    cmdSql = New SqlCommand
    cmdSql.CommandType = Data.CommandType.StoredProcedure
    cmdSql.CommandText = "spGetNews"
    cmdSql.Connection = connSql

    Dim prmParameter As SqlParameter

    prmParameter = New SqlParameter("@iPageIndex", Data.SqlDbType.Int)
    prmParameter.Direction = Data.ParameterDirection.Input
    prmParameter.Value = iCurrentPage
    cmdSql.Parameters.Add(prmParameter)

    prmParameter = New SqlParameter("@iMaxRows", Data.SqlDbType.Int)
    prmParameter.Direction = Data.ParameterDirection.Input
    prmParameter.Value = iMaxRows
    cmdSql.Parameters.Add(prmParameter)

    prmParameter = New SqlParameter("@iCategory", Data.SqlDbType.Int)
    prmParameter.Direction = Data.ParameterDirection.Input
    prmParameter.Value = iCategory
    cmdSql.Parameters.Add(prmParameter)

    prmParameter = New SqlParameter("@strSearch", Data.SqlDbType.VarChar, 100)
    prmParameter.Direction = Data.ParameterDirection.Input
    prmParameter.Value = strSearchText
    cmdSql.Parameters.Add(prmParameter)

    connSql.Open()
    gvGrid.DataSource = cmdSql.ExecuteReader
    gvGrid.DataBind()
    connSql.Close()

    ' Paging
    If gvGrid.Rows.Count < 1 Then
        divPager.InnerHtml = ""
    Else
        Dim iPages As Integer = 0
        Dim iRemainder As Integer = 0
        iPages = iTotal / iMaxRows
        iRemainder = iTotal Mod iMaxRows
        If iRemainder > iMaxRows Then iPages += 1

        If iPages > 1 Then
            divPager.InnerHtml = "Page: "

            Dim i As Integer = 0
            For i = 1 To iPages
                If i <> iCurrentPage Then
                    divPager.InnerHtml += "<a href=""" & strPage & _
                                          "?pg=" & i & """>" & i & "</a>"
                Else
                    divPager.InnerHtml += i.ToString
                End If
                If i < iPages Then divPager.InnerHtml += " | "
            Next
        End If
    End If
End Sub

最后,我编译链接以在 RowDataBound 事件中查看完整的文章

Protected Sub gvNews_RowDataBound(ByVal sender As Object, _
         ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
         Handles gvNews.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then
    ' Build link to full article
        e.Row.Cells(4).Text = "<a href=""NewsArticle.aspx?id=" & _
                              gvNews.DataKeys(e.Row.RowIndex)("intUniqueID") & _
                              "&pg=" & iCurrentPage & "&cID=" & _
                              iCategory & """>View complete article</a>"
    End If
End Sub

就这样,这应该可以帮助您入门。 如果您在站点上启动并运行此程序需要任何帮助,请随时与我联系。

© . All rights reserved.