![]() |
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
Liste der Anhänge anzeigen (Anzahl: 1)
So, das Beispielprojekt ist fertig. Ihr findet es im Anhang.
|
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
Liste der Anhänge anzeigen (Anzahl: 2)
So ganz habe ich das nicht durchblickt, aber ein DataModule schaut beim erzeugen sofort nach, ob es sich irgendwo einklinken (aufdrängeln ;-) ) kann.
In der Konsequenz sollte das zur Folge haben, dass man nicht zwei DataModules mit gleichen Komponenten verwenden kann. Na ja, es ist etwas verworren. Im Projekt habe ich mal die Functionen aus Classes.pas herauskopiert und Breakpoints gesetzt. Die Überwachung der globalen DBEdit "E" zeigt dann, wann E ein DataSet zugewiesen wird. DataSet toleriert dabei, dass der aktuelle Klassentyp nicht mehr TMyCustomDM ist (oder so ähnlich :freak:). |
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
In UMyCustomForm ist die Unit UMyCustomDM eingebunden. Deshalb kannst du dort im MyDBEdit unter DataSource MyCustomDM.MyDS eintragen.
TMyForm ist von TMyCustomForm abgeleitet und erbt auch die Einstellungen aus der dfm des Vorfahren. Beim Laden des Forms wird dann für den Wert MyCustomDM.MyDS ein GlobalFixup gespeichert und hinterher, wenn du TMyDM erstellst und zuweist, sorgt GlobalFixupReferences dafür, dass an den Stellen, wo diese Referenz über den Designer zugewiesen wurde, die neue Referenz zugewiesen wird. |
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
@ stahli: Die von dir angesprochene Zeile
Delphi-Quellcode:
lädt das Datamodule aus der DFM. Da passiert noch nichts weiter bzgl. der Verknüpfung zwischen DM und DBEdit. Erst nachdem ich mich in diesen Aufruf weiter reindebuggt habe, bin ich auf die von Stevie angesprochene Funktion Classes.GlobalFixupReferences gestoßen. Diese ruft wiederum Forms.FindGlobalComponent auf.
Instance := ReadComponent(Instance); // <----------------------------------
Und bei diesen 2 letzten Funktionen wird es interessant: Nach jeder Erstellung einer Form oder eines Datenmodules werden Verknüpfungen von Controls (wie meinem DBEdit) auf andere Forms und Datenmodule aufgelöst, und zwar basierend auf der Eigenschaft Name. Das ganze wird auf Basis von Screen.Forms und Screen.DataModules durchgeführt. Das interessante dabei: Bei meiner Instanzierung von MyDM wird zuerst eine Instanz von TMyCustomDM aus dem DFM gelesen (mit Name = MyCustomDM, wie in UMyCustomDM.dfm angegeben). Gibt es noch nicht aufgelöste Verknüpfungen/Referenzen (wie bei der DataSource-Property meines DBEdits), dann werden diese gesucht (und in meinem Fall gefunden: Name = MyCustomDM, wie im DBEdit angegeben). Anschließend wird über die Instanz von TMyCustomDM die Instanz von TMyDM "drübergelesen" - hier wird der Name mit MyDM überschrieben, was dann zur Laufzeit angezeigt wird. Quintessenz: Die ganze Verknüpfung basiert nicht auf der evtl. nicht vorhandenen globalen Variable, wie Anfangs vermutet wurde, sondern auf der Eigenschaft Name. Und: Name wird für jede einzelne Vererbungsebene geprüft (im Beispiel zuerst MyCustomDM und dann MyDM). Ergo: Dass diese Verknüpfung von DBEdit und MyCustomDM funktioniert, ist nicht nur zufällig und ich kann mich darauf verlassen, dass es immer funktioniert. Ich muss sagen, das ist ein cleveres System, was sich die Designer da ausgedacht haben! p.s.: Erklärung von FindGlobalComponent auf englisch: ![]() |
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
Na dann wissen wir ja "bescheid".
Es ist aber doch recht überraschend, wie das im Detail umgesetzt ist. Insb. dass dieses "binding" auch beim händischen Erzeugen eines DataModule erfolgt und dass auch die ParentClassTypes für die Zuordnung herangezogen werden. Ich hätte jedenfalls damit so nicht gerechnet. |
AW: Wie kommt ein TDBEdit an die Instanz meines DataModules? Warum/Wie funktioniert e
Es gibt noch eine Unwägbarkeit bei dem Ganzen: Ob das funktioniert, ist von der Erstellungsreihenfolge abhängig! Der Ablauf, den ich in meinem letzten Beitrag beschrieben habe, läuft nur dann so ab, wenn das DBEdit vor dem Datenmodul erstellt wird. Ansonsten sieht der Ablauf folgendermaßen aus:
Zuerst wird das Datenmodul erzeugt. Zu dieser Zeit bestehen keine nicht aufgelösten Abhängigkeiten. Nach der Erzeugung des Datenmoduls hat Screen.DataModules genau einen Eintrag: Ein Datenmodul mit Name "MyDM". Ein Datenmodul mit Name "MyCustomDM" hat nur während der Instanzierung von TMyDM kurzzeitig existiert. Wenn jetzt danach DBEdit instanziert wird, dann kann die Abhängigkeit "MyCustomDM.DS" nicht aufgelöst werden, da weder ein Formular noch ein Datenmodul mit Namen "MyCustomDM" existiert. Man kann das im Beispielprojekt leicht testen, wenn man den Konstruktor von TMyForm folgendermaßen umbaut (Das Datenmodul vor dem inherited-Aufruf instanziert):
Delphi-Quellcode:
In dem Fall kann die Abhängigkeit nicht mehr aufgelöst werden und beim Klick auf DBEdit kommt die Meldung "nil".
constructor TMyForm.Create(AOwner: TComponent);
begin SetDM(TMyDM.Create(Self)); //wenn Owner freigegeben wird, wird DM automatisch mit freigegeben inherited; end; Ein weiterer Fallstrick: Instanziert man anschließend (z.B. per Buttonclick) eine weitere Instanz von TMyDM, dann wird die Abhängigkeit von DBEdit auf diese Instanz aufgelöst. Ergo: Abhängigkeiten zu Formularen/Datenmodulen , die niemals selbst instanziert werden (nur davon abgeleitete Klassen werden instanziert) sind mit Vorsicht zu genießen, da sie immer auf das erste passende Formular/Datenmodul aufgelöst werden, das nach dem Control instanziert wird. Somit ist die Erstellungsreihenfolge von entscheidender Bedeutung. Mein Vorschlag, um diese Probleme zu umgehen: In den Fällen, in denen Abhängigkeiten zu Datenmodulen notwendig sind, die nicht direkt instanziert werden (sondern nur deren Nachkommen), sowie bei Datenmodulen, die mehrfach instanziert werden (wobei mir dazu grad kein Anwendungsfall einfällt), sollte folgendermaßen vorgegangen werden: Auf der Form mit den DB-Controls liegt ein (oder mehrere) entsprechendes Datasource, welches bei der Instanzierung der Form mit der Query aus dem DM verbunden wird (Das DM muss also zwingend vorher instanziert worden sein). Somit gibt es keine zur Designtime definierten Abhängigkeiten mehr, deren Auflösung die Probleme verursacht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz