AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Form + DataModule mehrere Instanzen

Ein Thema von Nersgatt · begonnen am 31. Jul 2017 · letzter Beitrag vom 31. Jul 2017
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.538 Beiträge
 
Delphi 12 Athens
 
#1

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 12:35
Nee, dein Problem ist hierbei eher, dass du bei dmFoo := TdmFoo.Create(Self) die globale Variable verwendest, anstatt einer lokalen Variable (ein Feld in TfrmFoo).

Tipp: Am Einfachsten immer als Erstes diese globale Variable löschen (außer "eine" Instanz davon lässt du automatisch von Delphi erzeugen > siehe DPR/Projektoptionen)
Und schon kommt man garnicht erst auf die Idee diese Variable ausversehn nutzen zu wollen.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (31. Jul 2017 um 12:37 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#2

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 12:39
Nee, dein Problem ist hierbei eher, dass du bei dmFoo := TdmFoo.Create(Self) die globale Variable verwendest, anstatt einer lokalen Variable (ein Feld in TfrmFoo).
Eine lokale Variable würde sehr gern verwenden, wenn ich wüsste, wie ich dann im Objektinspektor angeben kann, dass die Datenquelle FdmFoo.dsDaten ist und nicht dmFoo.dsDaten.
Natürlich könnte ich im Quellcode die Properties setzen. Aber dann verliere ich ja alle Vorteile, die das "R" im Wort "RAD" repräsentiert.
Jens
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.740 Beiträge
 
Delphi 6 Enterprise
 
#3

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 12:50
In dem Fall wäre es vllt. nötig, auf das Datenmodul zu verzichten und den ganzen Nichtvisuellen Teil auch auf die Form zu packen. Vielleicht nicht schön/übersichtlich, aber es funzt. Dies ist mMn ein Problem der Kategorie: "Irgendeinen Tod musst du sterben".
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.538 Beiträge
 
Delphi 12 Athens
 
#4

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 12:52
Das leider garnicht.
Praktisch kannst du im Formdesigner immer nur mit einer globalen Instanz (Signleton) deines DatenModuls arbeiten.

Du kannst aber im Create, vor dem Inherited eine Instanz deines Datenmoduls erzeugen. (es darf aber zur Laufzeit keine automatisch erzeugte Instanz dieses Moduls existieren, bzw. diese wird vorher umbenannt oder freigegeben)
DatenModule registrieren sich global im Delphi und der Form-Loader findet sie dann über ihren Namen, bzw. mann kann sich selber ein GetGlobalDataModule-Event registrieren.

Nach dem Laden (nach dem Create-Inherited oder spätestens im TForm.Loaded) dann das Datenmodul umbenennen (oder den Namen löschen > '' ), damit es mit späteren Instanzen deiner Form keine Überschneidungen gibt.

In der IDE muß aber eine "globale" Instanz vorhanden sein.
Gegen diese kannst du dann Designen (in der DFM wird der Name gespeichert) und beim Laden deiner Form im laufenden Programm wird dann jeweils die aktuelle/individuelle Instanz mit diesem Namen verwendet.

Statt vorher eine neue Datenmodul-Instanz zu erzeugen erstmal die globale Instanz verwenden und dann nach dem Laden der Form die "Globale" umbenennen, eine neue Instanz mit dem alten Namen erzeugen und der globalen Variable zuweisen (für ein eventuell nachfolgendes Laden weiterer Formen)




Tipp:
Wir haben bei uns ein paar DatenModule, die aber in verschiedenen Packages liegen und von der IDE leider nicht immer gefunden werden, wenn man nicht zufällig die Unit dieses DatenModules geöffnet hat, wenn gerade ein anderes Package aktiv ist.
Delphi scheint da nicht immer alle Packages "geladen" zu haben und dann existiert keine Instanz dieses Datenmoduls, was dann beim Öffnen der Form im FormEditor gern mal knallt.

Es gibt zwar in den geladenen DesignPackages nochmal eine Instanz, aber diese wird nicht vom FormDesigner gefunden, bzw. diese manuell erstellten Module werden nicht gefunden-
Aus diesem Grund hab ich unsere Instanzen der DesignTime-Packages auch nochmal manuell in der IDE "registriert".
Delphi-Quellcode:
RegisterFindGlobalComponentProc(FindGlobalModules); // im Class-Constructor des TIDEHelperModul
UnregisterFindGlobalComponentProc(FindGlobalModules);

class function TIDEHelperModul.FindGlobalModules(const Name: string): TComponent;
begin
  Result := nil;
  if SameText(Name, 'DM1') then Result := UDM1.DM1;
  if SameText(Name, 'DMSys') then Result := USysModule.DMSys;
end;



Alternativ eben nochmal der Vorschlag von nahpets.
Zitat:
Delphi-Quellcode:
procedure TfmMeinDataModulForm.SetDataSource(ADataModule : TDataModule);
begin
  fDataModule := ADataModule;
  if Assigned(fDataModule) then begin
    ... // eventuell erforderliche weitere Zuweisungen, Plausibilitätsprüfungen ...,
        // in Bezug auf das DataModule.
        // Z. B.: Sind dort die erforderlichen DataSets ... vorhanden ...
  end;
end;
Siehe die Kommentare.
Im OI nichts zuweisen, sondern das im Setter der Form an die Unterkomponenten durchreichen.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (31. Jul 2017 um 13:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 13:06
Du kannst aber im Create, vor dem Inherited eine Instanz deines Datenmoduls erzeugen. (es darf aber zur Laufzeit keine automatisch erzeugte Instanz dieses Moduls existieren, bzw. diese wird vorher umbenannt oder freigegeben)
DatenModule registrieren sich global im Delphi und der Form-Loader findet sie dann über ihren Namen, bzw. mann kann sich selber ein GetGlobalDataModule-Event registrieren.

Nach dem Laden (nach dem Create-Inherited oder spätestens im TForm.Loaded) dann das Datenmodul umbenennen (oder den Namen löschen > '' )
Genau das ist der Hinweis, den ich gesucht habe. Die Zuordnung passiert scheinbar über den Namen.
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:
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;
Freigabe des Datenmoduls dann im Destructor des Formulars.

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).
Jens
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.538 Beiträge
 
Delphi 12 Athens
 
#6

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 13:26
Delphi-Quellcode:
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;
Ich weiß, das Owner-Property ist ReadOnly, aber eigentlich ist die Owner-Beziehung das nicht.

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;
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (31. Jul 2017 um 13:42 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 13:33
Ah, super danke!
Das erspart das Freigeben des Datenmoduls im Destructor (was sicher sonst hier und da mal vergessen wird... )
Jens
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.752 Beiträge
 
Delphi 12 Athens
 
#8

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 14:37
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.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming

Geändert von Uwe Raabe (31. Jul 2017 um 15:10 Uhr) Grund: Form-Erzeugung
  Mit Zitat antworten Zitat
Benutzerbild von smallie
smallie

Registriert seit: 8. Jan 2013
19 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 16:00
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.
"There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.538 Beiträge
 
Delphi 12 Athens
 
#10

AW: Form + DataModule mehrere Instanzen

  Alt 31. Jul 2017, 16:03
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.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:20 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