需求
Delphi 的 DBGrid 通過 DataSource 綁定到一個 DataSet 顯示數據表里面的 N 多條記錄。如果我想給每條記錄加一個 CheckBox 讓用戶去勾選,該怎么做?
以下描述,使用的 DBGrid 是 DBGrieEh。
Delphi 自帶的 DBGrid 要加 CheckBox 比較麻煩一點,這里不提。
解決方案之一:
在 DataSet 里面增加一個內部計算字段,字段的數據類型是 Boolean,用于勾選。
1. 在設計期為 DataSet 創建對應數據庫的固定字段;
2. 設計期,為 DataSet 新增一個字段,我在這里給字段取名字 Checked,字段類型選擇?fkInternalCalc,字段的數據類型選擇 Boolean;
3. 設計期,為 DBGrid 添加固定字段。
4. 執行程序,加載數據,就會看到設計期為 DataSet 添加的 Checked 字段,呈現為檢查框的模樣。使用鼠標點擊可以勾選。
5. 我們的代碼如何獲取用戶勾選了哪些記錄?對 DataSet 逐條記錄循環,查看 Checked 字段的值是否為 True。
此方案的問題:
用戶勾選后,DataSet 處于編輯狀態,勾選(對 Checked 字段的值的更改)還沒有 Post,此時讀 DataSet 對應的字段的值,可能還是 False。當然,用戶勾選后,用鼠標順帶點一下別的記錄,使得 DataSet 自動執行 Post,就沒這個問題了。但這樣做多一個操作,并且使用者可能忘記這個操作,導致程序執行結果和預期不符。?
解決方案之二
不需要給 DataSet 增加一個計算字段,僅僅是設置 DBGridEh 的屬性就可以解決。并且沒有方案一的那個讓操作者迷惑的問題。
1. DBGridEh 的屬性 Options 里面的 dgMultiSelect 設置為 True;設計期的話,就是屬性面板里面找到這個屬性,勾選它。
2. DBGridEh 的屬性 IndicatorOptions 里面的 gioShowRowselCheckboxesEh 設置為 True。設計期的話,同樣是屬性面板里面找到這個屬性,勾選上。
搞定這兩步,運行起來,加載數據庫的數據,DBGridEh 的第一列就是 CheckBox 檢查框。不需要它對應的表有 Boolean 類型的字段。
這個檢查框,用戶可以點擊勾選。那么,我們怎么用代碼來檢查用戶勾選了啥?
假設這個 DBGridEh 對應的表,有一個主鍵字段是? SNO,那么,讀到用戶勾選的記錄的 SNO 就知道用戶勾選了那幾條記錄。
代碼如下
procedure TForm3.Button5Click(Sender: TObject);
vari: Integer;ABookMark, ABK: TBookMark;
beginABK := ClientDataSet1.GetBookmark;? //先保存當前位置,搞完循環后方便游標回到當前位置for i := 0 to DBGridEh1.SelectedRows.Count -1 dobeginABookMark := DBGridEh1.SelectedRows.Items[i]; //這是個 BookMarkClientDataSet1.GotoBookmark(ABookMark);? //游標走到這個 BookmarkMemo1.Lines.Add(ClientDataSet1.FieldByName('SNO').AsString); //勾選的記錄的編號end;ClientDataSet1.GotoBookmark(ABK);? //游標回到最開始的位置。
end;
上述代碼,是對 DBGridEh 的選擇行數做一個循環,然后去它對應的 DataSet 讀一個唯一字段(比如主鍵)的值,就知道用戶選擇了哪幾條記錄。這里不需要擔心用戶勾選后 DataSet 沒有 Post 而找不到勾選記錄的情況。
結論
使用 DBGridEh 的話,方法之二用戶更友好。也無需為 DataSet 增加計算字段,僅僅將?DBGridEh 的兩個屬性值設置為 True 搞定。