2008年9月25日

DataGridView 分頁

坎尼又來講分頁了 (你怎麼那麼愛講
不過標題上寫的是 DataGridView 分頁
「到底是 DataGrid 還是 GridView 啦」

哈 其實是 System.Windows.Form.DataGridView

這東西是 WinForm 裡的資料展現容器
和 WebForm 上的 DataGrid 還是 GridView 看起來很像
其實骨子裡相同點倒是不多

首先稍微講一下 WinForm 和 WebForm 的差異
1.WinForm 裡沒有 也不需要 Session
2.資料繫結無需再下 DataBind() 動作 (也沒有 DataBind() Method)
3.ComboBox的 SelectedIndex 事件,在後端指定Index 也會去執行 Event
4.下拉選單在 WinForm 叫做 ComboBox 而且它只有 Text
好啦 目前大概知道這些就夠用了 (再寫下去篇幅會太長

再來就是講一下 為什麼要講 DataGridView 的分頁
因為它沒有內建分頁功能啊啊啊啊啊

所以坎尼用了最古老的方式 -- 自己算目前頁數顯示資料
另外分頁的控制項沿用之前坎尼講的 自訂分頁

不過由於沒有 PagerTemplate
所以坎尼拉了個 Panel 再把拉了四個 LinkLabel 再加個 ComboBox 和 Label
先來看一下畫面


先宣告個全域變數 iCurrentPage 用來記錄目前的頁數

再來是寫換頁事件 這邊會看到坎尼用 LinkLabel Tag 來記錄按下的鈕
當然 Tag 裡可以換成 Previous Next First Last 這種比較容易了解的文字

可以看到 Tag 裡值為 1 為第一頁 2為上一頁 3為下一頁 4是最後一頁
這邊要注意的是 坎尼用 -5 這個當做 iCurrentPage 的數值

接著就會跳往 ShowData 函式
可以看到 其實 ShowData 裡的東西實在沒什麼 XD
這裡會呼叫 Paging() 以取得繫結的 DataTable

再來就是最重要的 Paging 函式 先來看上半部
先由 GetData 函式取得查詢出來的資料 並宣告一個 dtReturn
接著就是判斷 iCurrentPage
這邊就會看到坎尼把最後一頁的參數設為 -5 的用意

先來看 if 的前半段 如果 iCurrentPage 大於等於 最大頁數
iCurrentPage 當然就是最後一頁 (iCurrentPage = dt.Rows.Count/10)
iCurrentPage 若小於0 當然就是第一頁 (iCurrentPage = 0)

由上面可知 不管怎麼按 上一頁 iCurrentPage 最少都只會是 -1
所以坎尼才會用 -5 來當最後一頁的參數 (當然 要用 -4 -6 -8 都可以
這邊還要注意一點的就是 坎尼是用一頁十個項目為基準

然後會看到一些 enable 的設定 只是讓顯示上好看一點 沒加上去也沒關係


繼續下半部
下拉選單的項目坎尼是讓系統每跑一次就重新產生
再把目前的SelectedIndex 設成 iCurrentPage (這邊會引發 IndexChanged 事件

最後是最重要的部分:建立要資料繫結的 DataTable
由於每頁為十筆 所以目標頁面的 index 是以 10 * iCurrentPage 起點 往後十筆
並將這些Row的資料 AdddtReturn
然後回傳給 DataGridView 做資料繫結的動作

最後是 下拉選單 的 IndexChanged 事件
這邊加入判斷式 為了不讓程式進入無窮迴圈 XDDD
想知道為什麼的人 可以將 if註解掉 然後設中斷點跑跑看 :p

下面就是執行畫面 (一張跑到上面去了)


好啦 又是落落長的一篇 (上次講分頁也是這樣
都不知道大家有沒有聽懂? (抓頭

總結一下
WinForm 的 DataGridView 沒有分頁事件
只要給予 DataSource 則會跑出所有資料
所以坎尼將資料處理過 每次都給 十筆資料 的 DataTable
這樣資料繫結完就會只跑出十筆

ps. 範例裡是以一頁10筆做基準
若想自訂分頁筆數 只要將 paging 裡的 10 改成 其他數字即可

13 則留言:

匿名 提到...

iCurrentPage 的-5可用-1來取代吧~

坎尼 提到...

-5 是用來當最後一頁的 flag
所以改成 -1 會 confuse 後來的工程師

但這篇其實是很久之前寫的
flag 和判斷式改為用明確的命名會比較恰當些

匿名 提到...

請問為什麼我打完之後顯示 GetData不存在目前內容中?

坎尼 提到...

Hi,

GetData() 是我自己寫的 Method,用來從 database 裡取值的喔~

所以先檢視你有實作 GetData() 嗎?

匿名 提到...

沒有欸....我是新手...所以搞不太懂該怎麼做QWQ...想說做著做著怎麼沒有這個關鍵字可以用

坎尼 提到...

//實作你抓取資料的方法
private DataTable GetData()
{
return new DataTable();
}

匿名 提到...

請問GetData裡面使用DataSet也可以嗎(我原先的連接是使用DataSet)
還是要改成DataTable?

可以請您提供簡單的範例嗎?

坎尼 提到...

當然可以啊~
你先去了解一下 DataSet 和 DataTable 的關係,就知道怎麼做了~

匿名 提到...

唔...我的問題其實是不知道我寫到哪邊可以停止
因為我把原先的連線字串全放進去的話
我的dataGridView1 Show不出任何東西
所以才想說是不是用法的關係
想參考一下我是寫到Adapter就好還是???

我知道DataSet是個存放Table的容器
但是具體怎麼使用真的看了很多文章都很頭痛

匿名 提到...

(剛才的留言好像被吃掉了)

其實我的問題是因為
我把原先的連線字串整個放進去GETDATA之後
我的dataGridView1 秀不出資料來...
我才想說是不是哪部分多寫或少寫造成的原因
又或者都要同步使用DataTable

才想問大大能不能提供您寫的GETDATA方式讓我參考看看

坎尼 提到...

1) 你先確認你有沒有抓到資料 (很重要

2) 確定有資料,在原本的 DataSet 加上 DataSet.Tables[0]
就會是你的資料了


如果是依照這個範例,基本上不會有其他問題

ps. 因為你沒有登入 Google 帳號,所以 Google 容易把匿名留言當作垃圾留言,丟到留言垃圾筒裡去

Unknown 提到...

1)確認有抓到資料
如果我直接在Loading裡取用Getdata,會顯示資料

2)在原本的 DataSet 加上 DataSet.Tables[0]這句不是很明白欸
意思是在Adapter.Fill(dt, "Table");變成dt.Tables[0]?
還是其他的呢?

3)我去登入Google帳號了~感謝大大提醒

4)我逐步執行程式的時候 ShowData那邊我進不去 會不會是我也該改那邊?

坎尼 提到...

ShowData() 那邊是要把排序過的資料做 Binding()
可以去看一下那邊的 Exception 內容

如果沒有要做分頁,可以把自己寫的 Paging() 關掉

Google Spreadsheet 裡用規則運算式

最近因為工作關係,遇到要用 Google Form 及 Google Sheet 所以研究了 Google Sheet 裡的一些 function 怎麼用 首先,分享一下如何在 Google Sheet 裡用規則運算 :D