天天看點

WinForm程式虛拟分頁(實時加載資料)

Windows應用程式中很少見有分頁的程式

檔案夾中有上萬個檔案的時候微軟也沒讓使用者來翻頁檢視清單

記事本中的文字,某個系統功能的清單也都沒有分頁。(Word文檔是個例外)

知道web中的分頁是怎麼做出來的朋友一定知道winform做分頁會更簡單

winform程式一樣也不允許使用者一下子把資料庫中上萬條資料全部檢索出來

那麼怎麼讓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結構

WinForm程式虛拟分頁(實時加載資料)
WinForm程式虛拟分頁(實時加載資料)

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結構的定義)

WinForm程式虛拟分頁(實時加載資料)
WinForm程式虛拟分頁(實時加載資料)

        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用了三個多小時