如何在GridView上添加分页?

huangapple go评论87阅读模式
英文:

How can I add paging on GridView?

问题

我有一个关于 GridView 的问题。尽管我启用了 AllowPaging,但仍然看不到页面数字并且无法浏览页面。数据根据页面大小获取,但分页细节(如页面数量)未显示,因此无法进一步导航。

<asp:GridView ID="recItemsGrid" runat="server" AutoGenerateColumns="false" Width="100%" BorderColor="#f5f5f5"
    BorderStyle="Solid" BorderWidth="1px" AllowPaging="true" PageSize="3" OnPageIndexChanging="recItems_OnPageIndexChanging">
private void BindGridView()
{
    int pageIndex = recItemsGrid.PageIndex;
    int pageSize = recItemsGrid.PageSize;
    GetItemsFromDataSource(pageIndex, pageSize);            
}

protected void GetItemsFromDataSource(int pageIndex, int pageSize)
{
    var paging = new ReconciliationItemPagingRequest(pageIndex, pageSize);

    ReconciliationItemPagingResult recItemPagingResult =
        ReconciliationItemService.GetJournalItemDetails(Convert.ToInt32(ParentPage.AssignmentID), paging);

    recItemsGrid.VirtualItemCount = recItemPagingResult.TotalRecordCount;
    recItemsGrid.DataSource = recItemPagingResult.Data;

    if (recItemsGrid.VirtualItemCount == 0)
    {
        lblNoItems.Visible = true;
        recItemsGrid.Visible = false;
    }
    else
    {
        lblNoItems.Visible = false;
        recItemsGrid.Visible = true;

        if (recItemsGrid.VirtualItemCount > 1)
        {
            recItemsGrid.Columns[0].Visible = true;
        }
        else
        {
            recItemsGrid.Columns[0].Visible = false;
        }
    }

    recItemsGrid.DataSource = recItemPagingResult.Data;
    recItemsGrid.DataBind();            
} 

protected void recItems_OnPageIndexChanging(object sender, GridViewPageEventArgs e)
{
    recItemsGrid.PageIndex = e.NewPageIndex;
    this.BindGridView();
}
英文:

I have a problem with a GridView. Even though I enabled AllowPaging I still can't see the page numbers and navigate through pages. The data is brought according to the page size, but the paging details (like the number of the pages do not appear so I can navigate further).

&lt;asp:GridView ID=&quot;recItemsGrid&quot; runat=&quot;server&quot; AutoGenerateColumns=&quot;false&quot; Width=&quot;100%&quot; BorderColor=&quot;#f5f5f5&quot;
                    BorderStyle=&quot;Solid&quot; BorderWidth=&quot;1px&quot; AllowPaging=&quot;true&quot; PageSize=&quot;3&quot; OnPageIndexChanging=&quot;recItems_OnPageIndexChanging&quot;&gt;
private void BindGridView()
        {
            int pageIndex = recItemsGrid.PageIndex;
            int pageSize = recItemsGrid.PageSize;
            GetItemsFromDataSource(pageIndex, pageSize);            
        }

        protected void GetItemsFromDataSource(int pageIndex, int pageSize)
        {
            var paging = new ReconciliationItemPagingRequest(pageIndex, pageSize);

            ReconciliationItemPagingResult recItemPagingResult =
                ReconciliationItemService.GetJournalItemDetails(Convert.ToInt32(ParentPage.AssignmentID), paging);

            recItemsGrid.VirtualItemCount = recItemPagingResult.TotalRecordCount;
            recItemsGrid.DataSource = recItemPagingResult.Data;

            if (recItemsGrid.VirtualItemCount == 0)
            {
                lblNoItems.Visible = true;
                recItemsGrid.Visible = false;
            }
            else
            {
                lblNoItems.Visible = false;
                recItemsGrid.Visible = true;

                if (recItemsGrid.VirtualItemCount &gt; 1)
                {
                    recItemsGrid.Columns[0].Visible = true;
                }
                else
                {
                    recItemsGrid.Columns[0].Visible = false;
                }
            }

            recItemsGrid.DataSource = recItemPagingResult.Data;
            recItemsGrid.DataBind();            
        } 
        
        protected void recItems_OnPageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            recItemsGrid.PageIndex = e.NewPageIndex;
            this.BindGridView();
        }

答案1

得分: 0

代码部分不翻译,以下是翻译好的部分:

使用内置的分页控件的问题在于它仍然期望总行数。

所以,如果有100行数据,那么你的数据源必须返回100行,否则页码和计数都会混乱。

现在,猜测一下你的代码?你希望以正确的方式完成这个,只从数据库中拉取实际的行数。

你没有提到总行数。然而,如果数据的总拉取是200行,那么我会让它流动到内置的数据分页系统中。

记住,内置的数据分页系统实际上是在作弊。它从来没有限制数据的拉取,只是通过限制向网页输出的数据量来使页面工作“合理”。

所以,内置的分页控件?嗯,最多只能处理大约200或者可能是300行。而且你每次重新绑定时都要“喂养”数据源的所有行(这就是它的工作原理)。

正如前面所提到的,如果你的数据集比200-300行还要大,那么你可能应该放弃内置的分页控件,自己编写一个。这样,你只拉取给定页面的行。

所以,要么移除你的代码,尝试只从数据源拉取一页行,总是将完整的数据集传递给GridView - 这就是内置的分页控件的工作方式。

一旦你只真正拉取一页数据行,那么页码计数将不起作用,并且会完全错误,因为页码计数是由你拉取的数据集的大小确定的。

所以,如果这个方案可行:

<asp:GridView ID="GHotels" runat="server" CssClass="table table-hover" 
    AutoGenerateColumns="false"
    width="45%" DataKeyNames="ID" AllowPaging="True" 
    OnPageIndexChanging="GHotels_PageIndexChanging" PageSize="6">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
        <asp:BoundField DataField="LastName" HeaderText="LastName" />
        <asp:BoundField DataField="HotelName" HeaderText="Hotel Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />                
    </Columns>
    <PagerStyle CssClass="GridPager" />
</asp:GridView>

以及代码后端:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
        LoadData();
}

void LoadData()
{
    using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
    {
        string strSQL = 
            @"SELECT * FROM tblHotels 
              WHERE Description is not null 
              ORDER BY HotelName";
        using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
        {
            DataTable rstData = new DataTable();
            conn.Open();
            rstData.Load(cmdSQL.ExecuteReader());
            GHotels.DataSource = rstData;
            GHotels.DataBind();
        }
    }
}

protected void GHotels_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    GHotels.PageIndex = e.NewPageIndex;
    LoadData();
}

你非常接近地注意到,实际上每次都会拉取完整的数据集。

因此,如果你要进行真正的数据库分页(内置的分页控件不支持此功能),那么最好是构建自己的分页系统。这肯定会比内置系统表现得更好,正如我所指出的,它实际上从不限制数据拉取,只是每次都拉取所有行,并使用该行数来确定分页控件中要显示的页面数量。然后从完整的数据集中拉取页面行。

自己编写分页控件应该不会太困难,而且性能会非常好,特别是如果你使用SQL服务器端的数据分页功能。这意味着你可以对任何大小的数据库进行分页,只需要从数据库中拉取一页数据行即可(SQL Server 2012或更高版本支持分页功能)。

我认为使用单选按钮列表是一个不错的选择,用于渲染“x”个按钮,这样还可以自动突出显示控件列表中的“一个项目”(用于当前页码)。

你没有提到你有多少行数据?但是,如果少于200行,那么请移除你传递页码的代码,只需始终将整个数据集传递给GridView,然后让分页控件为你提取一页数据。

英文:

Ok, the problem with using built-in pager is that it STILL expects the total number of rows.

so, if there is 100 rows, then your data source MUST return 100 rows else the page number and count will be all messed up.

Now, taking a "guess" at your code? You looking to do this the CORRECT way, and ONLY pull from the datbase the actual number of rows.

You don't mention the total row count. However, if the total raw pull of data is say 200 rows, then I would just let that flow though to the built in data pager system.

Remember, the built in data pager system actually cheats. It NEVER limited the data pull for you, but only made a page work "reasonable" well by limting the payload (output) to the web page.

so, the built in pager? Hum, good to a max of about 200 or maybe 300 rows tops. And you "just feed" the data source ALL THE ROWS each time on a re-bind. (that's how this works).

As noted, if you data set is larger then that 200-300 rows, then you probably should just dump the built in pager, and roll your own. That way, you ONLY pull the rows for the given page.

So, either remove your code that attempts to ONLY pull the page of rows from the data source, and ALWAYS feed the gv the full data set - that's how the built in pager works.

The instant you only REALLY pull one page of data rows, then the page count will not work and will be all wrong, since the page count is determined by the size of the data set you pull.

So, say this works:

        &lt;asp:GridView ID=&quot;GHotels&quot; runat=&quot;server&quot; CssClass=&quot;table table-hover&quot; 
            AutoGenerateColumns=&quot;false&quot;
            width=&quot;45%&quot; DataKeyNames=&quot;ID&quot; AllowPaging=&quot;True&quot; 
            OnPageIndexChanging=&quot;GHotels_PageIndexChanging&quot; PageSize=&quot;6&quot;   &gt;
            &lt;Columns&gt;
                &lt;asp:BoundField DataField=&quot;FirstName&quot; HeaderText=&quot;FirstName&quot;  /&gt;
                &lt;asp:BoundField DataField=&quot;LastName&quot; HeaderText=&quot;LastName&quot;    /&gt;
                &lt;asp:BoundField DataField=&quot;HotelName&quot; HeaderText=&quot;Hotel Name&quot;    /&gt;
                &lt;asp:BoundField DataField=&quot;Description&quot; HeaderText=&quot;Description&quot; ItemStyle-Width=&quot;270&quot; /&gt;                
            &lt;/Columns&gt;
            &lt;PagerStyle CssClass=&quot;GridPager&quot; /&gt;
        &lt;/asp:GridView&gt;

And code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();
    }

    void LoadData()
    {
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = 
                @&quot;SELECT * FROM tblHotels 
                  WHERE Description is not null 
                  ORDER BY HotelName&quot;;
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                DataTable rstData = new DataTable();
                conn.Open();
                rstData.Load(cmdSQL.ExecuteReader());
                GHotels.DataSource = rstData;
                GHotels.DataBind();
            }
        }
    }


    protected void GHotels_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        GHotels.PageIndex = e.NewPageIndex;
        LoadData();
    }

You note VERY close how in fact the FULL data set is pulled each time.

The result is thus this:

如何在GridView上添加分页?

So, if you going to do REAL data base paging (which the built in pager does not do), then you probably are better off to build your own pager system). It would certainly perform MUCH better then the built in system, which as I pointed out does not actually ever limit the data pulled, but ONLY ever pulls all rows each time, and uses that row count to determine the number of pages to put in the pager. And then pulls the page of rows out of the FULL data set.

It should be not all that difficult to roll your own pager, and the advantage would be fantastic performance, especially if you use SQL server side data paging ability. This would then mean, suggest that you could page any size database, and you would ONLY be pulling one page of data and rows from the database. (sql server 2012 or later does have paging support).

I think using a radio button list would be a good choice for a control to render "x" number of buttons, and that would also thus have automatic "one item" in the control list to be highlighted (for the page number you are on).

You don't mention how many rows you have? But, if less then say 200, then remove the code you have that passes the page number, and just ALWAYS feed the GV the whole data set, and let the pager pull out the one page for you.

huangapple
  • 本文由 发表于 2023年7月7日 01:15:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631165.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定