【C#】避免 DataGridView 排序導致取錯行:請用 DataBoundItem 而非 Rows[e.RowIndex]
Copyright Notice: This article is an original work licensed under the CC 4.0 BY-NC-ND license.
If you wish to repost this article, please include the original source link and this copyright notice.
Source link: https://v2know.com/article/1157
在使用 WinForms 的 DataGridView 搭配 DataTable 或其他繫結資料來源時,你是否曾遇過以下狀況?
使用者編輯某一列的資料,但實際讀取或更新的卻是另一筆記錄?
這種問題多半發生在你直接用 dgv.Rows[e.RowIndex] 存取儲存格資料,而此時 DataGridView 剛好啟用了排序或過濾功能。本文將說明這個問題的成因,並提供正確的寫法。
❌ 錯誤寫法:Rows[e.RowIndex]
我們常見的寫法如下:
object keyValue = dgv.Rows[e.RowIndex].Cells[meta.KeyColumn].Value;
這段程式碼看似沒問題,但如果你的 DataGridView 是透過 DataSource 綁定了 DataTable,一旦啟用了排序(點擊欄位標題排序)或過濾功能,那麼 Rows[e.RowIndex] 的行就不再對應於 DataTable 中的原始資料順序。
換句話說,你以為你正在取用第 N 筆資料,但實際上拿到的可能是另一筆。
✅ 正確寫法:使用 DataBoundItem
解法其實很簡單:繞過 DataGridView 的顯示順序,直接存取資料來源本體。
var row = ((DataRowView)dgv.Rows[e.RowIndex].DataBoundItem).Row;
object keyValue = row[meta.KeyColumn];
這段寫法中,我們透過 DataBoundItem 取得資料列的 DataRowView,再從中拿到真實的 DataRow。這樣可以確保你抓到的資料始終是原始資料來源中的正確一筆,無論使用者如何排序或篩選畫面。
🧪 測試方式建議
-
對
DataGridView綁定一個DataTable。 -
啟用
AllowUserToOrderColumns = true。 -
實作
CellValueChanged或CellEndEdit。 -
測試排序前後,所取得的
row["主鍵"]是否仍一致。
📝 小結
| 寫法 | 是否正確 | 說明 |
|---|---|---|
dgv.Rows[e.RowIndex].Cells[...] |
❌ 錯誤 | 容易因排序導致取錯行 |
((DataRowView)dgv.Rows[e.RowIndex].DataBoundItem).Row |
✅ 正確 | 可準確取得原始資料行 |
在 WinForms 資料繫結的世界裡,DataBoundItem 是你和資料來源間的「真實通道」。別再依賴 DataGridView 排序後的表面行順序,否則 debug 時你可能會陷入一場無止盡的謎團。
This article was last edited at