Um auf Feldebene zu sehen, was sich geändert hat, musst du meines Wissens immer mit der
DB vergleichen.
Ich gehe dazu ganz grob folgendermaßen vor:
- bei der Erzeugung der Maske suche ich alle Controls auf der Maske heraus, die einen Datenbank-Bezug haben
(bei denen es entweder ein Property "DataSource" oder "DataSet" gibt oder ein Property "DataField" oder "Field", die ihrerseits ein Property "DataSource" oder "DataSet" haben);
die merke ich mir samt den dazugehörigen "TFields" in einer speziellen Liste
- wenn ein "DataSource" auf der Maske den Status auf "dsEdit" setzt, durchsuche ich die Liste nach geänderten "TFields"
(bei denen prüfe/vergleiche ich Value, NewValue und ggf. OldValue)
- ist ein Feld geändert, suche ich in der o.a. Liste nach Controls, die sich auf die "DataSource" und das Feld beziehen und setze deren Fontfarbe auf "rot"
Das funktioniert relativ gut - hat noch ein paar Spezialfälle, die ich gesondert handhabe, aber im großen und ganzen funktioniert das
Vielleicht wäre es sinnvoll, die Daten in einem ClientDataSet zu verwalten, statt direkt mit der
DB zu kommunizieren. Du willst die Daten ja sowieso erst nach Bestätigung durch den Anwender an die
DB schicken. Da bietet sich so eine Zwischenschicht schon an.
Prinzipiell gebe ich Dir da Recht - wäre wahrscheinlich auch zunftsträchtiger (da ja dann endlich ggf. die
BDE-Bezüge eliminierbar wären).
Ich habe in der Richtung auch bereits Experimente in meinem Code gemacht - bin dann dort aber auf andere Probleme gestoßen, die nicht so einfach behebbar waren --> also leider auch keine "einfache" Lösung
Aktuell habe ich in dem Zusammenhang schon wieder ein komisches Problem:
Ich will ja den korrekten Status sowohl eines einzelnen Records als auch des gesamten Queries (bzw. DataSet) bestimmen - dazu gehört auch herauszufinden, ob ein Record gelöscht wurde.
Um solche Records überhaupt im DataSet zu haben, verwende ich folgenden Code (Auschnitt):
Delphi-Quellcode:
function DSRecGetState( const ds_ : TDataSet ) : TUpdateStatus;
var
dsBDE : TBDEDataSet;
updRecTypes : TUpdateRecordTypes;
begin
...
Log( ds_ ); // 1. Aufruf
dsBDE := nil;
if ( ds_ is TBDEDataSet ) then begin
dsBDE := TBDEDataSet( ds_ );
end;
updRectTypes := [];
if ( Assigned(dsBDE) and dsBDE.CachedUpdates ) then begin
updRecTypes := dsBDE.UpdateRecordTypes;
if ( NOT (rtDeleted in updRecTypes) ) then begin
dsBDE.UpdateRecordTypes := dsBDE.UpdateRecordTypes + [ rtDeleted ];
end;
Log( ds_ ); // 2. Aufruf
end;
...
end;
beim ersten Log-Aufruf kommt folgendes:
Code:
Active=true, RecordCount=1, CanModify=true, Modified=true, UpdateStatus()=Unmodified, State=dsEdit, CachedUpdates=true, UpdatesPending=false
beim zweiten Log-Aufruf kommt folgendes:
Code:
Active=true, RecordCount=1, CanModify=true, Modified=false, UpdateStatus()=Modified, State=dsBrowse, CachedUpdates=true, UpdatesPending=true
Was soll das? Wieso wird durch das Verändern des "UpdateRecordTypes"-Set der Status des einen (!) vorhandenen Records geändert?
Er veliert das Modified-Flag und auch der State des gesamten Queries geht von "dsEdit" auf "dsBrowse"!???
Lt. Doku heißt es doch:
An application might also use UpdateRecordTypes like a filter to temporarily limit visible records to those added or inserted by the user during the current session.
Das habe ich so interpretiert, dass man das problemlos während der Laufzeit ändern kann (am Ende o.a. Funktion stelle ich das auch wieder auf den ursprünglichen Wert zurück)...