前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WinForm程序虚拟分页(实时加载数据)

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

作者头像
liulun
发布2022-05-09 11:11:56
9250
发布2022-05-09 11:11:56
举报
文章被收录于专栏:liulunliulun

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

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

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

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

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

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

代码如下:

一:窗体类

代码语言:javascript
复制
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结构

代码语言:javascript
复制
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);
            }
            /// <summary>
            /// 获取当前页起始行的index
            /// </summary>
            public int LowestIndex
            {
                get
                {
                    return lowestIndexValue;
                }
            }
            /// <summary>
            /// 获取当前页的结束行的Index
            /// </summary>
            public int HighestIndex
            {
                get
                {
                    return highestIndexValue;
                }
            }
            /// <summary>
            /// 获取起始行的index
            /// </summary>
            /// <param name="rowIndex"></param>
            /// <returns></returns>
            public static int MapToLowerBoundary(int rowIndex)
            {
                return (rowIndex / RowsPerPage) * RowsPerPage;
            }
            /// <summary>
            /// 获取结束行的index
            /// </summary>
            /// <param name="rowIndex"></param>
            /// <returns></returns>
            private static int MapToUpperBoundary(int rowIndex)
            {
                return MapToLowerBoundary(rowIndex) + RowsPerPage - 1;
            }
            /// <summary>
            /// 获取当前行的页码
            /// </summary>
            /// <param name="rowIndex"></param>
            /// <returns></returns>
            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结构的定义)

代码语言:javascript
复制
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();
        }
        /// <summary>
        /// 判断两个缓存页中是否有当前行的数据
        /// </summary>
        /// <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 true;
                }
            return false;
        }
        /// <summary>
        /// 绘制表格前获取数据的方法
        /// </summary>
        /// <param name="rowIndex">当前行的index</param>
        /// <param name="columnIndex">当前列的index</param>
        /// <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);
            }
        }
        /// <summary>
        /// 程序初始化时获取第一页和第二页的数据
        /// </summary>
        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;
        }
        /// <summary>
        /// 获取下一页or上一页未缓存的数据,反回当前Cell的值
        /// </summary>
        /// <param name="rowIndex">当前行的index</param>
        /// <param name="columnIndex">当前列的index</param>
        /// <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);
        }
        /// <summary>
        /// 判断根据当前行获取的数据应该放在哪个页当中缓存起来
        /// </summary>
        /// <param name="rowIndex">当前行的index</param>
        /// <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;
            }
            else
            {
                int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;
                int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;
                if (offsetFromPage0 < offsetFromPage1)
                {
                    return 1;
                }
                return 0;
            }
        }
        /// <summary>
        /// 判断当前行是否在缓存中
        /// </summary>
        /// <param name="pageNumber">页的index</param>
        /// <param name="rowIndex">当前行的index</param>
        /// <returns>如果在返回true</returns>
        private bool IsRowCachedInPage(int pageNumber, int rowIndex)
        {
            return rowIndex <= cachePages[pageNumber].HighestIndex && rowIndex >= cachePages[pageNumber].LowestIndex;
        }

写这个Demo用了三个多小时

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2009-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档