波斯马BOSSMA Information Technology

GridView自定义分页的实现方式

发布时间:2011年9月23日 / 分类:ASP.NET / 18,440 次浏览 / 评论

此篇文章中提到的“GridView自定义分页”是指:每一页的数据都从数据源查询,每次绑定到GridView的数据只包含当页的数据,总记录数由其它程序提供给GridView,而不是由GridView自己计算。

之前我写过一篇文章叫“GridView通用分页模型”,主要是应用于绑定全部数据,依靠GridView去计算分页数量、每一页该显示哪些数据等;虽然也有考虑自定义分页,但是没有经过测试,有点想当然的感觉。最近又有相关的需求才发现实现不了,于是经过一番修改,实现了自定义分页的功能。

先来看看几个问题:
1、设置分页数量
GridView要进行分页需要知道分页数量,有一个属性PageCount,可惜只能get不能set。反编看看它是怎么实现的,貌似是在CreateChildControls方法中通过pagedDataSource计算出来的,而pagedDataSource是GridView对DataSource进行的封装,超复杂的方法看不下去。于是乎想到一个办法重写PageCount,那么就要继承GridView创建一个自定义控件了。

2、设置记录总数
要计算分页数量还得需要记录总数和分页大小,分页大小可以用通过PageSize属性直接设置,记录总数却没有现成的属性或方法来设置。没办法只能再添加一个属性VirtualRecordCount用来保存记录总数。

3、区分自定义分页和GridView内置分页
还是通过添加属性的方式,添加AllowCustomPaging属性,为true时代表使用自定义分页,默认为false。

说了这么多,来看看代码吧:
1、自定义控件:

public class VirtualPagerGridView : GridView
    {
        private int? virtualRecordCount;
        /// <summary>
        /// Gets or Sets the Total Records for pagination,
        /// its important to set the value of Total
        /// Records BEFORE binding the data to the grid.
        /// </summary>
        public int VirtualRecordCount
        {
            get
            {
                if (virtualRecordCount == null)
                {
                    if (ViewState["VirtualRecordCount"] == null)
                    {
                        VirtualRecordCount = PageIndex;
                    }
                    else
                    {
                        VirtualRecordCount = (int)ViewState["VirtualRecordCount"];
                    }
                }
                return virtualRecordCount.Value;
            }

            set
            {
                virtualRecordCount = value;
                ViewState["VirtualRecordCount"] = value;
            }
        }

        private bool allowCustomPaging = false;
        /// <summary>
        /// 设置是否允许自定义分页
        /// </summary>
        public bool AllowCustomPaging
        {
            get
            {
                if (ViewState["IsCustomPaging"] != null)
                {
                    allowCustomPaging = (bool)ViewState["IsCustomPaging"];
                }

                return allowCustomPaging;
            }

            set
            {
                allowCustomPaging = value;
                ViewState["IsCustomPaging"] = value;
            }
        }

        /// <summary>
        /// 返回自定义分页数量
        /// </summary>
        public override int PageCount
        {
            get
            {
                if (!AllowCustomPaging)
                {
                    return base.PageCount;
                }
                else
                {
                    return Convert.ToInt32(Math.Ceiling((decimal)VirtualRecordCount / (decimal)this.PageSize));
                }
            }
        }

        /// <summary>
        /// 返回当前分页页码
        /// </summary>
        public override int PageIndex
        {
            get
            {
                if (!AllowCustomPaging)
                {
                    return base.PageIndex;
                }
                else
                {
                    if (ViewState["VirtualPageIndex"] == null)
                    {
                        return base.PageIndex;
                    }
                    else
                    {
                        return (int)ViewState["VirtualPageIndex"];
                    }
                }
            }

            set
            {
                base.PageIndex = value;
                ViewState["VirtualPageIndex"] = value;
            }
        }

        /// <summary>
        /// Override it to avoid the popup message of not handling this event and
        /// to reset the selected index again.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPageIndexChanging(GridViewPageEventArgs e)
        {
            PageIndex = e.NewPageIndex;
            this.SelectedIndex = -1;

            base.OnPageIndexChanging(e);
        }

        /// <summary>
        /// This will work unless you display empty rows in your gridview for some reason.
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <param name="dataSourceIndex"></param>
        /// <param name="rowType"></param>
        /// <param name="rowState"></param>
        /// <returns></returns>
        protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
        {
            if (dataSourceIndex <= this.VirtualRecordCount)
            {
                return base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState);
            }
            else
            {
                return base.CreateRow(rowIndex, dataSourceIndex, DataControlRowType.EmptyDataRow, DataControlRowState.Normal);
            }
        }
    }

2、使用
原有的代码结构不需要改变,只需要修改控件标签名和数据绑定部分:

我这里控件标签为:

cc1:VirtualPagerGridView

绑定数据部分:

GridView1.AllowCustomPaging = true;
GridView1.VirtualRecordCount = recordCount;

第一句设置使用自定义分页,第二句设置总记录数。绑定数据还是原来的方式,只不过获取到的数据只需要当页的数据就可以了。

关于GridView的自定义分页网上有两篇不错的,不过大家可以参考:

http://www.codeproject.com/KB/webforms/ASPEnhancedGridView.aspx?display=Print

http://siderite.blogspot.com/2007/08/changing-gridview-pagecount.html

只不过这两个有些不太适合我的情况,因为我使用了PagerTemplate,里边使用了<% …%>,导致一些因为数据处理有前有后而产生的数值不正确的问题。

这个分页是集成到GridView中的,不需要其它的第三方组件,也不是通过自己写按钮事件的方式来实现的。有可能不适合你的情况,请慎重选择。

如果有什么问题,请留言。

最后点击这里下载示例程序

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自波斯马,原文地址《GridView自定义分页的实现方式

关键字:

建议订阅本站,及时阅读最新文章!
【上一篇】 【下一篇】

目前有4 条评论

  1. jueee 0楼:

    补充一下 删除是在外面按钮调用的 不是OnRowDeleted事件

  2. jueee 0楼:

    你好 请教一下 如果翻页到了最后一页 而且只有一条数据。 这时删掉这一条数据后 如果能自动跳转到前一页上呢?

  3. bossma 0楼:

    @xialin
    // AllowCacheDatatSource 默认为true,适用于将全部数据一次性绑定到GridView,在分页的过程中数据源不会发生变化。
    // 如果不允许缓存DataSource,则每次页码变化时都调用GridView_DataBind,每次获取数据重新绑定,数据源的实时性更强。
    VirtualPagerGridView1.AllowCacheDatatSource = false;

    // 如果允许自定义分页,则每次获取指定页的数据
    // 同时不能缓存DataSource,即AllowCacheDatatSource=false
    VirtualPagerGridView1.AllowCustomPaging = true;
    VirtualPagerGridView1.VirtualRecordCount = 45;

    通过VirtualRecordCount设置总条数。

  4. xialin 0楼:

    其他都很好用,只是我是新手,使用中因为自己更改了页面,设置为从数据库获取数据,结果无法显示总条数。请大哥指点

发表评论