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结构

Code
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结构的定义)

 

Code

        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用了三个多小时

时间: 2024-10-26 09:52:10

WinForm程序虚拟分页(实时加载数据)的相关文章

DevExpress的GridControl的实时加载数据解决方案(取代分页)

传统的Winform(不使用第三方控件)针对DataGridView的实时加载数据的文章请看这里 http://www.cnblogs.com/liulun/archive/2009/09/28/1576000.html DevExpress是一套第三方控件 其中有类似DataGridView的控件 今天把针对DevExpress.XtraGrid.GridControl实时加载数据的功能开发出来了 分享给大家 欢迎讨论 Codeusing System;using System.Collect

Android实现ListView分页自动加载数据的方法_Android

Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样会有更好的用户体验.因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.例如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据. 下面通过一个Demo来展示ListView功能如何实现:该Demo通过在ListVie

Android实现ListView分页自动加载数据的方法

Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样会有更好的用户体验.因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.例如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"查看更多"按钮,用户点击后,加载下一页数据. 下面通过一个Demo来展示ListView功能如何实现:该Demo通过在ListVie

Android中ListView如何分页加载数据_Android

熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们今天就要讲一讲列表组件ListView加载数据的相关内容.通常来说,一个应用在展现大量数据时,不会将全部的可用数据都呈现给用户,因为这不管对于服务端还是客户端来说都是不小的压力,因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.比如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"加载更多"按钮,用户点

Android开发之ListView利用OnScrollListener实现分页加载数据

上篇博文和大家分享了下拉刷新,这是一个用户体验非常好的操作方式.新浪微薄就是使用这种方式的典型. 还有个问题,当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了.通过分页分次加载数据,用户看多少就去加载多少. 通常这也分为两种方式,一种是设置一个按钮,用户点击即加载.另一种是当用户滑动到底部时自动加载.今天我就和大家分享一下这个功能的实现.

c# excel-c# 把excel数据封装,每次程序运行自动加载数据?

问题描述 c# 把excel数据封装,每次程序运行自动加载数据? c#里要用到excel里的数据,能不能把数据封装处理,每次运行程序都自动加载相关数据? 解决方案 可以啊,用NPOI读Excel. 建议把Excel里的数据导入到数据库里,轻量级数据库有sqlite

Android实现listview动态加载数据分页的两种方法_Android

在android开发中,经常需要使用数据分页,比如要实现一个新闻列表的显示,或者博文列表的显示,不可能第一次加载就展示出全部,这就需要使用分页的方法来加载数据,在android中Handler经常用来在耗时的工作中,它接收子线程发送的数据,并使用数据配合更新UI,AsyncTask是在一个线程中执行耗时操作然后把结果传给UI线程,不需要你亲自去管理线程和句柄. 一.使用Handler+线程方法1.基础知识Handler在android系统中,主要负责发送和接收消息,它的用途主要有以下两种: (1

Android应用中ListView利用OnScrollListener分页加载数据_Android

当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了.通过分页分次加载数据,用户看多少就去加载多少. 通常这也分为两种方式,一种是设置一个按钮,用户点击即加载.另一种是当用户滑动到底部时自动加载.今天我就和大家分享一下这个功能的实现. 首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图: <?xml

Android中ListView分页加载数据功能实现_Android

 熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,我们今天就要讲一讲列表组件ListView加载数据的相关内容.通常来说,一个应用在展现大量数据时,不会将全部的可用数据都呈现给用户,因为这不管对于服务端还是客户端来说都是不小的压力,因此,很多应用都是采用分批次加载的形式来获取用户所需的数据.比如:微博客户端可能会在用户滑动至列表底端时自动加载下一页数据,也可能在底部放置一个"加载更多"按钮,用户