天天看点

WinForm程序虚拟分页(实时加载数据)

Windows应用程序中很少见有分页的程序

文件夹中有上万个文件的时候微软也没让用户来翻页查看列表

记事本中的文字,某个系统功能的列表也都没有分页。(Word文档是个例外)

知道web中的分页是怎么做出来的朋友一定知道winform做分页会更简单

winform程序一样也不允许用户一下子把数据库中上万条数据全部检索出来

那么怎么让winform程序即不用翻页,又能分部加载数据呢

代码如下:

一:窗体类

Code

    public partial class Form1 : Form

    {

        private Cache memoryCache;

        public Form1()

        {

            InitializeComponent();

        }

        protected override void OnLoad(EventArgs e)

            WebPager pager = InitPager();

            memoryCache = new Cache(pager, 10);

            dataGridView1.RowCount = pager.TotalCount;

            for (int i = 1; i < memoryCache.ColumnCollenction.Count; i++)

            {

                dataGridView1.Columns.Add(memoryCache.ColumnCollenction[i].ColumnName, memoryCache.ColumnCollenction[i].ColumnName);

            }

            //为DataGridView提供自己的数据管理操作

            dataGridView1.VirtualMode = true;            

            this.dataGridView1.AllowUserToAddRows = false;

            this.dataGridView1.AllowUserToOrderColumns = false;

            this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

            // Adjust the column widths based on the displayed values.

            this.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);

            //VirtualMode为TRUE并且需要显示新数据时发生

            dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);

            base.OnLoad(e);

        void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)

            e.Value = memoryCache.RetrieveElement(e.RowIndex, e.ColumnIndex);

        private WebPager InitPager()

            //设置分页类

            WebPager pagerData = new WebPager();

            pagerData.TableName = @"T_ENTERPRISE_ENTERPRISEJOB";

            pagerData.OrderStr = "order by EEJ_CREATETIME desc";

            pagerData.PageSize = 10;

            return pagerData;

    }

二:Page结构

public struct DataPage

            public DataTable table;

            private int lowestIndexValue;

            private int highestIndexValue;

            /// <summary>

            /// 一页数据的结构。构造函数

            /// </summary>

            /// <param name="table">数据源</param>

            /// <param name="rowIndex">当前行的index</param>

            public DataPage(DataTable table, int rowIndex)

                this.table = table;

                lowestIndexValue = MapToLowerBoundary(rowIndex);

                highestIndexValue = MapToUpperBoundary(rowIndex);

            /// 获取当前页起始行的index

            public int LowestIndex

                get

                {

                    return lowestIndexValue;

                }

            /// 获取当前页的结束行的Index

            public int HighestIndex

                    return highestIndexValue;

            /// 获取起始行的index

            /// <param name="rowIndex"></param>

            /// <returns></returns>

            public static int MapToLowerBoundary(int rowIndex)

                return (rowIndex / RowsPerPage) * RowsPerPage;

            /// 获取结束行的index

            private static int MapToUpperBoundary(int rowIndex)

                return MapToLowerBoundary(rowIndex) + RowsPerPage - 1;

            /// 获取当前行的页码

            public static int MapCurrentPageIndex(int rowIndex)

                int pageindex = rowIndex / RowsPerPage;

                if (rowIndex % RowsPerPage > 0)

                    return ++pageindex;

                return pageindex;

三:WebPager数据访问类

通过访问数据库的分页存储过程获取某一页的数据

由于这个类的代码并非我写的,所以这里不在公布了

此类公开的几个字段和一个方法如下

每页显示条数  PageSize

当前显示第几页  PageIndex

共几页  PageCount

所有的条目数  TotalCount

分页的表或者实体 TableName

查询的字段  QueryFieldName

排序字段  OrderStr

查询的条件  QueryCondition

获取数据  public DataTable QuickPageData()

四:Cache类(这个类包含了Page结构的定义)

        private static int RowsPerPage;

        private DataPage[] cachePages;

        public DataColumnCollection ColumnCollenction { get; set; }

        private WebPager dataSupply;

        /// <summary>

        /// 构造函数

        /// </summary>

        /// <param name="dataSupplier">分页类</param>

        /// <param name="rowsPerPage">一页几行</param>

        public Cache(WebPager dataSupplier, int rowsPerPage)

            dataSupply = dataSupplier;

            Cache.RowsPerPage = rowsPerPage;

            LoadFirstTwoPages();

        /// 判断两个缓存页中是否有当前行的数据

        /// <param name="rowIndex">当前行的index</param>

        /// <param name="columnIndex">当前列的index</param>

        /// <param name="element">当前Cell的值</param>

        /// <returns>如果有  返回true</returns>

        private bool IfPageCached_ThenSetElement(int rowIndex,int columnIndex, ref string element)

                if (IsRowCachedInPage(0, rowIndex))

                    element = cachePages[0].table.Rows[rowIndex % RowsPerPage][columnIndex].ToString();

                    return true;

                else if (IsRowCachedInPage(1, rowIndex))

                    element = cachePages[1].table.Rows[rowIndex % RowsPerPage][columnIndex].ToString();

            return false;

        /// 绘制表格前获取数据的方法

        /// <returns>返回表格的值</returns>

        public string RetrieveElement(int rowIndex, int columnIndex)

            string element = null;

            if (IfPageCached_ThenSetElement(rowIndex, columnIndex, ref element))

                return element;

            else

                return RetrieveData_CacheIt_ThenReturnElement(rowIndex, columnIndex);

        /// 程序初始化时获取第一页和第二页的数据

        private void LoadFirstTwoPages()

            dataSupply.PageIndex = 1;

            DataPage p1 = new DataPage(dataSupply.QuickPageData(), 0);

            dataSupply.PageIndex = 2;

            DataPage p2 = new DataPage(dataSupply.QuickPageData(), RowsPerPage);

            cachePages = new DataPage[]{p1,p2};

            this.ColumnCollenction = p1.table.Columns;

        /// 获取下一页or上一页未缓存的数据,反回当前Cell的值

        /// <returns>反回当前Cell的值</returns>

        private string RetrieveData_CacheIt_ThenReturnElement(int rowIndex, int columnIndex)

            dataSupply.PageIndex = DataPage.MapCurrentPageIndex(rowIndex);

            cachePages[GetIndexToUnusedPage(rowIndex)] = new DataPage(dataSupply.QuickPageData(), rowIndex);

            return RetrieveElement(rowIndex, columnIndex);

        /// 判断根据当前行获取的数据应该放在哪个页当中缓存起来

        /// <returns>页的index</returns>

        private int GetIndexToUnusedPage(int rowIndex)

            if (rowIndex > cachePages[0].HighestIndex && rowIndex > cachePages[1].HighestIndex)

                int offsetFromPage0 = rowIndex - cachePages[0].HighestIndex;

                int offsetFromPage1 = rowIndex - cachePages[1].HighestIndex;

                if (offsetFromPage0 < offsetFromPage1)

                    return 1;

                return 0;

                int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;

                int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;

        /// 判断当前行是否在缓存中

        /// <param name="pageNumber">页的index</param>

        /// <returns>如果在返回true</returns>

        private bool IsRowCachedInPage(int pageNumber, int rowIndex)

            return rowIndex <= cachePages[pageNumber].HighestIndex && rowIndex >= cachePages[pageNumber].LowestIndex;

写这个Demo用了三个多小时