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

  • 相关阅读:
    Ubuntu系统
    demo日常报错
    python 实现两个多维数组去重处理
    奔跑检测
    安装Win11如何绕过TPM2.0的安全限制?
    Nginx的Rewrite
    gvim 配置
    Tokyo Cabinet和Tokyo Tyrant及PHP扩展包的安装
    fm rf 删除 恢复
    提高页面loadtime的几个方法
  • 原文地址:https://www.cnblogs.com/liulun/p/1576000.html
Copyright © 2020-2023  润新知