![]() |
AW: Form + DataModule mehrere Instanzen
Zitat:
Wenn man zuerst das Datenmodul erzeugt, dann das Formular und dann den Namen des Datenmoduls ändert, kann man weitere Instanzen erzeugen. Ich hab das jetzt mal so gemacht:
Delphi-Quellcode:
Freigabe des Datenmoduls dann im Destructor des Formulars.
function CreateFoo(AOwner : TComponent) : TfrmFoo;
var dm : TdmFoo; begin dm := TdmFoo.Create(nil); try result := TfrmFoo.Create(AOwner); result.DataModule := dm; // für Zugriffe auf das Datenmodul im Code dm.Name := ''; except dm.Free; raise; end; end; Kann man bestimmt noch hübscher lösen, aber es zeigt erst mal, worauf es ankommt (nämlich den Namen des Datenmoduls an der richtigen Stelle zu manipulieren). |
AW: Form + DataModule mehrere Instanzen
Delphi-Quellcode:
Ich weiß, das Owner-Property ist ReadOnly, aber eigentlich ist die Owner-Beziehung das nicht. :angle:
dm := TdmFoo.Create(nil);
try result := TfrmFoo.Create(AOwner); result.DataModule := dm; // für Zugriffe auf das Datenmodul im Code dm.Owner := result; // oder result.InsertComponent(dm); mit dm.Owner.RemoveComponent(dm) wenn dm.Owner<>nil dm.Name := ''; except dm.Free; raise; end;
Delphi-Quellcode:
type
TComponentHelper = class helper for TComponent private function GetOwner: TComponent; procedure SetOwner(NewOwner: TComponent); public property Owner: TComponent read GetOwner write SetOwner; function SecureOwner: TComponent; // if Assigned(Self) then Result:=Owner else Result:=nil; function SecureName: string; {$REGION 'Documentation'} /// <summary> /// Setzt C.Name für das Error-Logging, wenn das nicht geht, dann wird eine ID angehängt. (z.B. zwei mal /// DB.LoadBool zur selben Zeit) /// </summary> {$ENDREGION} procedure SetErrorName(NewName: string); end; { TComponentHelper } function TComponentHelper.GetOwner: TComponent; begin Result := inherited Owner; end; function TComponentHelper.SecureName: string; begin if not Assigned(Self) then Result := '(nil)' else try Result := Name; except Result := '(except)'; end; end; function TComponentHelper.SecureOwner: TComponent; begin if not Assigned(Self) then Result := nil else try Result := inherited Owner; except Result := nil; end; end; procedure TComponentHelper.SetErrorName(NewName: string); begin try if Name = NewName then Exit; if (NewName <> '') and Assigned(Owner) and Assigned(Owner.FindComponent(NewName)) then Name := NewName + Format('_%p', [Pointer(Self)]) else Name := NewName; except end; end; procedure TComponentHelper.SetOwner(NewOwner: TComponent); begin if Assigned(NewOwner) then NewOwner.InsertComponent(Self) else if Assigned(Owner) then Owner.RemoveComponent(Self); end; |
AW: Form + DataModule mehrere Instanzen
Ah, super danke! :thumb:
Das erspart das Freigeben des Datenmoduls im Destructor (was sicher sonst hier und da mal vergessen wird... :cyclops: ) |
AW: Form + DataModule mehrere Instanzen
Es geht auch noch etwas einfacher. Beim Auflösen der Referenzen haben Komponenten der Form-Instanz Vorrang. Hier ein Form mit Referenz auf ein globales Datenmodul, die zur Laufzeit auf die lokale Instanz umgebogen wird.
Delphi-Quellcode:
type
TMyDataModule = class(TDataModule) HostdbConnection: TFDConnection; TestTable: TFDQuery; private public end; var MyDataModule: TMyDataModule;
Delphi-Quellcode:
object DataSource1: TDataSource DataSet = MyDataModule.TestTable Left = 304 Top = 64 end
Delphi-Quellcode:
type
TForm198 = class(TForm) DataSource1: TDataSource; DBGrid1: TDBGrid; private FMyDataModule: TMyDataModule; protected property MyDataModule: TMyDataModule read FMyDataModule; public constructor Create(AOwner: TComponent); override; end; constructor TForm198.Create(AOwner: TComponent); begin FMyDataModule := TMyDataModule.Create(Self); { Wenn die globale Instanz von MyDataModule hier bereits existiert, wird der Name dieser lokalen Instanz beim Laden der DFM verändert. Daher setzen wir den wieder zurück, sonst werden die Referenzen nicht richtig aufgelöst. Da es eine lokale Instanz des Forms ist, führt das hier zu keinerlei Kollisionen } FMyDataModule.Name := 'MyDataModule'; { Wichtig! Das muss vor dem inherited geschehen. } inherited; end; EDIT: Die Forms kann man damit wieder ganz normal über TForm198.Create(???) erzeugen und muss sich um die Datenmodule gar nicht kümmern. |
AW: Form + DataModule mehrere Instanzen
Die globale Variable braucht es dafür nicht. Es gilt ausschließlich der Name und die "automatische" globale Registrierung der TDataModule.
Und ja, diese Variante hatte ich auch schon beschrieben und wie bereits gesagt, muß man nachher das DataModul umbenennen, da sonst mehrere Datenmodule mit dem selben Namen global registriert sind und welches davon dann für die Verlinkung genommen wird, das ist potentiell zufällig. Erstmal gibt es die Liste in TScreen.DataModule Der DFM-Loader verwendet nun Classes.FindGlobalComponent, welches über RegisterFindGlobalComponentProc(Forms.FindGlobalComponent) in Forms.pas auf Screen.DataModules geht, und schnappt sich die erste Instanz aus Screen.DataModules, mit dem kleinsten Index und dem gewünschten Name, aber das muß nicht unbedingt die von deinem letzten TDataModule.Create sein. |
AW: Form + DataModule mehrere Instanzen
Zitat:
Und das lokale Datenmodul kann sehr wohl seinen Namen behalten, solange man das beschriebene Verfahren konsistent in allen Forms durchführt. |
AW: Form + DataModule mehrere Instanzen
Ahhhhh, garnicht dran gedacht.
Der böse Owner und FindComponent. Im FormDesigner wird aber auch hier dennoch die globale Instanz verwendet. (außer man leitet die Form ab und baut das in den Vorfahren ein ... vorausgesetzt die Ableitung wird richtig im FormDesigner geladen) |
AW: Form + DataModule mehrere Instanzen
Die Anforderung nach eigenen Instanzen für das Datenmodul habe ich noch nicht verstanden.
Sollte es nicht reichen, die Datensourcen auf das Formular zu setzen, dann können die Formulare unabhängig voneinander in den Daten scrollen. Das Datenmodul darf Singleton bleiben. |
AW: Form + DataModule mehrere Instanzen
Jedes Formular mit seinem eigenen DatenModul und den darauf liegenden DataSources,
sonst zeigt doch jede Form das Gleiche an, wenn die alle mit der selben DataSource arbeiten. :zwinker: |
AW: Form + DataModule mehrere Instanzen
Ein DesignTimePackage mit
Delphi-Quellcode:
und schon kannst du das Datenmodul als Non-visuelle Komponente auch direkt auf die Form pappen, aber die Datenmodul-Komponente muß dort unbedingt einen anderen Namen bekommen, wie in der DFM des Datenmoduls steht.
RegisterComponents('DatenModule', [TMyDataModule]);
(sicherheitshalber SetName des DatenModule überschreiben und das unterbinden) Ob die DFM des Datenmoduls hier auch richtig geladen wird, kann ich jetzt nicht beurteilen, aber ich denke es könnte funktionieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:21 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