概念
前面的文章 FireDAC 學習 - 5 講到,將 FdQuery 和 FdMemTable 的 CachedUpdates 設置爲 True,然後在 FdMemTable 裏面編輯後,可以讀取到編輯改動的記錄,將編輯改動過的記錄輸出爲 Stream,再通過網絡將 Stream 送給 FdQuery 然後提交到數據庫。
CachedUpdates 方式下,所有對 FdQuery 或者 FdMemTable 裏面的記錄的修改,比如用戶在綁定的 DBGrid 裏面對數據做的修改,都緩存在內存裏面,用戶可以隨時對修改進行 Cancel 等操作(類似於一個 Undo 操作),直到執行了 ApplyUpdates 纔會真正寫入數據庫。
問題
用戶在 DGBrid 裏面對數據進行操作,修改了一條記錄的某個字段的內容,或者新增了幾條記錄,用戶都是能看到的。但刪除的記錄,用戶看不到。如果用戶想 Undo 刪除的記錄,用戶如果看不到,想不起來之前刪除的是哪條記錄,不知道是否該 Undo,怎麼辦?
解決方法
FdMemTable 有一個屬性:FilterChanges,這是一個集合屬性。在設計期屬性面板可以看到:
這裏默認沒有 rtDeleted,如果把 rtDeleted 加入集合(屬性面板裏面把 False 改爲 True),則即使刪除掉的記錄,在 DBGrid 裏面也顯示。
不過這樣帶來一個界面反饋的問題,刪除了一條記錄,DBGrid 裏面它仍然顯示,用戶搞不清楚剛纔那個刪除操作成功了沒有,會把人搞糊塗。
一個辦法是爲 FdMemTable 加上一個計算字段,用於顯示每條記錄的狀態,這樣即使該記錄存在,狀態顯示爲刪除,用戶就不會被搞糊塗。噹噹噹,先看效果圖:
實現上圖功能
1. 在 FdMemTable 裏面,增加一個計算字段。這個計算字段在所有字段排列的最後。
2. 爲 FdMemTable 的 OnCalcFields 事件增加事件代碼如下:
procedure TForm1.FDMemTable2CalcFields(DataSet: TDataSet);
begin
// FilterChanges 屬性默認包含 rtModified, rtInserted, rtUnmodified,沒包含 rtDeleted;
// 在CachedUpdate 狀態下,如果加上 rtDeleted,則被刪除的記錄,同樣顯示在 DGBrid 裏面。
//這裏增加一個計算字段來顯示每條記錄的編輯狀態,包括已經刪除的記錄。
case DataSet.UpdateStatus of
usUnmodified:
DataSet.Fields[DataSet.FieldCount -1].AsString :=
'Unmodified';
usModified:
DataSet.Fields[DataSet.FieldCount -1].AsString :=
'Modified';
usInserted:
DataSet.Fields[DataSet.FieldCount -1].AsString :=
'Inserted';
usDeleted:
DataSet.Fields[DataSet.FieldCount -1].AsString :=
'Deleted';
end;
end;
3. 設置 FdMemTable 的 FilterChanges 屬性。這裏我增加了代碼,用於切換顯示/不顯示被刪除的記錄,不想看到被刪除的記錄的時候就不顯示,增加一個按鈕,按鈕的事件代碼如下:
procedure TForm1.Button8Click(Sender: TObject);
begin
if rtDeleted in FdMemTable2.FilterChanges then
begin
FdMemTable2.FilterChanges := FdMemTable2.FilterChanges - [rtDeleted];
end
else
begin
FdMemTable2.FilterChanges := FdMemTable2.FilterChanges + [rtDeleted];
end;
end;
上述代碼是對 FilterChanges 這個集合進行操作,減號就是從集合中去掉一個元素,加號是爲集合增加一個元素。如果增加了 rtDeleted 則會在 DBGrid 裏面顯示出已經被刪除的記錄。
上面效果圖的第三條,運行時點擊這個 Button8,則會顯示/不顯示切換。切換到不顯示,則上面效果圖的第三條不會出現在 DBGrid 裏面。
這個功能非常好,提供給了用戶一個非常直觀的觀察自己對這些記錄做了什麼操作的機會,用戶因此可以決定是否需要撤回之前的操作。如何撤回,這裏就不多說了,最簡單的辦法是調用 FdMemTable 的 CancelUpdates 方法。