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 { getset; }
        
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用了三个多小时

posted @ 2009-09-28 21:47  liulun  阅读(4803)  评论(4编辑  收藏  举报