Hallo!
Das OnExit-Ereignis ist nicht unbedingt ideal für derartige Prüfungen. Abgesehen von möglicherweise lange dauernden Prüfroutinen (vor allem, wenn hierzu Datenbankzugriffe erforderlich sind), welche vom Anwender als störend während der Eingabe empfunden werden, wird OnExit nämlich auch nur dann ausgelöst, wenn das Steuerelement tatsächlich verlassen wird (also den Eingabefokus verliert). Dies ist der Fall, wenn man per Tab oder Mausklick in ein anderes Eingabefeld wechselt, aber nicht, wenn z.B. zum Speichern ein Toolbar-Button angeklickt wird oder die entsprechende Tastenkombination (Shortcut) gedrückt wird! Fatal, wenn in diesem Fall wichtige Aktionen, die in der OnExit-Ereignisbehandlung implementiert sind, nicht ausgeführt werden...
Als Workaround kann man in den Aktionen wie Speichern o.ä. zu einem kleinen Trick greifen: man setzt einfach Self.ActiveControl auf nil, wodurch auf jeden Fall auch OnExit ausgelöst wird, selbst wenn der Eingabefokus nicht vom Anwender auf ein anderes Steuerelement gesetzt wurde!
Im folgenden Beispiel unterstelle ich jetzt einfach mal, dass Du eine Methode zum Speichern hast... ich nenne sie mal
ActionSave
Delphi-Quellcode:
function TfrmAdrEdit.ActionSave(): Boolean;
var
bOK: Boolean;
begin
bOK := True
// Sicherstellen, dass alle OnExit-Ereignisse ausgeführt wurden!
Self.ActiveControl := nil;
{ ... }
// Hier folgt der Code zum Speichern der Eingaben
{ ... }
Result := bOK;
end; // TfrmAdrEdit.ActionSave
Es ist aber gar nicht notwendig, noch während der Eingabe solche Prüfungen durchzuführen, es muss nur sichergestellt werden, DASS sie durchgeführt werden und zwar vor dem Speichern! Ein viel besserer und sauberer Ansatz ist es, grundsätzlich alle Gültigkeitsprüfungen (Validierungen) in einer zentralen Methode durchzuführen, welche dann vor dem eigentlichen Speichern aufgerufen wird. Das obige Beispiel würde dann so aussehen:
Delphi-Quellcode:
function TfrmAdrEdit.ActionSave(): Boolean;
var
bOK: Boolean;
begin
bOK := True
// Sicherstellen, dass alle OnExit-Ereignisse ausgeführt wurden!
Self.ActiveControl := nil;
// Gültigkeitsprüfungen
if bOK then
begin
bOK := ValidateData();
end;
// Speichern
if bOK then
begin
{ ... }
end;
Result := bOK;
end; // TfrmAdrEdit.ActionSave
function TfrmAdrEdit.ValidateData(): Boolean;
var
bOK: Boolean;
begin
bOK := True;
// AdrNr noch nicht vorhanden?
if bOK then
begin
// Hier folgt der Code zur Überprüfung, ob die eingegebene Adressnummer bereits
// vorhanden ist
{ ... }
// Wenn Adressnummer bereits vorhanden, Meldung anzeigen
if not bOK then
begin
{ ... }
end;
end;
// ggf. weitere Gültigkeitsprüfungen
if bOK then
begin
{ ... }
end;
Result := bOK;
end; // TfrmAdrEdit.ValidateData
Eine andere noch bessere Möglichkeit ist es, Deine Prüfung im BeforePost-Ereignis der DataSet-Komponente unterzubringen, denn dort gehört sie eigentlich auch hin...
Ich hoffe jetzt mal, das war verständlich genug und ich konnte Dir damit helfen...
Noch was zum Thema Primärschlüssel und Auto-Werte:
Hansa schrieb bereits, dass hier offenbar eine Verwechslung stattfand... Und er hat völlig Recht, ein Primärschlüsselwert darf niemals an die Oberfläche gelangen, d.h. er darf dem Anwender weder angezeigt werden, noch darf er jemals geändert werden - das macht nur Probleme! Die Adress-ID oder Adress-Nr um die es hier geht, kann also nur ein Sekundärschlüssel sein, d.h. ein zusätzliches Feld, welches eben auch eindeutig ist.
Ausserdem sollten auch grundsätzlich keine AutoInc-Felder verwendet werden, auch das macht früher oder später nur Probleme (s. auch Antwort von fiasko)! Etwas besser sind da schon die Generatoren/Sequenzen, wie sie bei richtigen Datenbanksystemen (Interbase, Oracle, MS
SQL, etc.) üblicherweise verwendet werden, hier hat man dann aber zusätzlichen Portierungsaufwand, wenn später mal das Datenbanksystem gewechselt werden sollte... und was, wenn das neue Ziel-Datenbanksystem keine Generatoren unterstützt?
Auch Lösungen mit eigenen Implementierungen über Zählertabellen o.ä. sind nicht wirklich so das Gelbe vom Ei... Eine Alternative ist die Verwendung von GUIDs. Diese sind wirklich immer eindeutig (theoretisch zumindest
und lassen sich leicht von der Applikation erzeugen. Jedoch sind diese alphanumerisch und 26 Zeichen lang...
Wie auch immer... egal, für welche Lösung man sich entscheidet, die Primärschlüsselwerte dürfen
niemals von der Applikation interpretiert werden (dürfen also keinen Informationsgehalt besitzen) und müssen
unveränderlich sein! Ausserdem empfiehlt es sich,
grundsätzlich nur Primärschlüssel zu verwenden, die aus einem
einzigen Feld bestehen. Dies macht das Leben deutlich einfacher...
Ich nenne meine Primärschlüsselfelder übrigens
immer ID und nicht etwa Adr_ID oder Adr_Nr oder sowas in der Art. Auch das hat schon vieles einfacher gemacht...
So... jetzt hör ich mal auf... für meinen ersten Beitrag ist das ja jetzt voll der Roman geworden....