Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TCollection speichert nicht im DFM, was fehlt? (https://www.delphipraxis.net/150434-tcollection-speichert-nicht-im-dfm-fehlt.html)

RSE 16. Apr 2010 12:57


TCollection speichert nicht im DFM, was fehlt?
 
Hallo,

ich bin dabei eine eigene Komponente zu entwickeln. Erstmalig tritt nun der Fall auf, dass ich eine Liste eigener Unterobjekte in meiner Komponente speichern muss. Dazu wurde mir im Thread Speichern eines Objekts mit einer Liste von Objekten im DFM geraten, mit TCollection und TCollectionItem zu arbeiten und schon würden die Unterobjekte im DFM-File automatisch mitgespeichert. Das ist leider nicht der Fall. Bestimmt habe ich TCollection falsch verwendet oder nicht alle notwendigen Anpassungen vorgenommen. Vielleicht spielt auch meine Delphi-Version eine Rolle (Delphi 5 Enterprise). Folgender Code stellt den Kern dar:

Delphi-Quellcode:
TMyItem = class(TCollectionItem)
    ...
end;

TMyItemList = class(TCollection)
  private
    FItems: array of TMyItem;
  protected
    function GetItem(AIndex: Integer): TMyItem;
    procedure SetItem(AIndex: Integer; AItem: TMyItem);
    ...
  public
    ...
    function Add: TCollectionItem; overload;
    function Add({eigene Argumente für Initialisierung}): TMyItem; overload;
    property Items[Index: Integer]: TMyItem read GetItem write SetItem; default;
end;

TCustomMyComp = class(TCustomControl)
  private
    FItems: TMyItemList;
    ...
  public
    ...
    property Items: TMyItemList read FItems;
end;
Die Property vom Typ TMyItemList ist published, der Property Editor von TCollection wird angezeigt und ich erstelle meine Items damit. Wenn ich allerdings die Form neu öffne (so dass er die Items aus der DFM laden müsste), sind sie nicht da. In der DFM wird auch nichts weiter erstellt (Unterobjekteintäge für meine Items).

Was muss ich tun, damit meine Items auch in der DFM gespeichert werden, wenn sie zur Entwurfszeit mit dem Property Editor von TCollection erstellt werden?

HeZa 16. Apr 2010 14:04

Re: TCollection speichert nicht im DFM, was fehlt?
 
du brauchst noch eine private variable FOwner vom Typ TComponent in TMyItemList und musst dann noch die beiden nachfolgenden Prozeduren wie folgt überschreiben.

Delphi-Quellcode:
constructor TMyItemList.Create(AOwner: TComponent);
begin
  inherited Create(TOurCollectionItem);
  FOwner := AOwner;
end;

function TMyItemList.GetOwner: TPersistent;
begin
  Result := FOwner;
end;
TCustomMyComp muss TMyItemList dann wie folgt initialisieren (wenn du es nicht bereits so gemacht hast):

Delphi-Quellcode:
FItems := TMyItemList.Create(self);
Ansonsten ist Creating Custom Delphi Components - Part II, Page 4: Collections sehr hilfreich oder auch ein Blick in die Delphi Sourcen (such dort Mal nach class(TCollection)).

Viel Erfolg noch.
Ciao HeZa

HeZa 16. Apr 2010 14:08

Re: TCollection speichert nicht im DFM, was fehlt?
 
Ich sehe gerade noch, die Funktion Add (ohne Parameter) sollte auch den Rückgabetyp TMyItem haben. Also so:

Delphi-Quellcode:
function Add: TMyItem; overload;
Viel Spaß
Ciao HeZa

Andreas L. 16. Apr 2010 14:11

Re: TCollection speichert nicht im DFM, was fehlt?
 
@Heza: So sollte der constructor von TCollection nicht überschrieben werden! Und da liegt auch nicht der Fehler ;-)

Die Daten werden nicht gespeichert weil die Eigenschaft Items als default-Eigenschaft definiert wird. Versuchs so:
Delphi-Quellcode:
  property Items[Index: Integer]: TMyItem read GetItem write SetItem;

RSE 16. Apr 2010 14:30

Re: TCollection speichert nicht im DFM, was fehlt?
 
Keiner der Vorschläge führt zum Erfolg. Ich werde eine neue Komponente bauen, die sonst keine Funktionalität enthält und das erneut testen. Diese werde ich, wenn sie nicht funktioniert, hier komplett posten. Weitere Vorschläge sind weiterhin willkommen.

RSE 16. Apr 2010 15:11

Re: TCollection speichert nicht im DFM, was fehlt?
 
Lösung: Die Items-Property in TCustomMyComp darf nicht readonly sein. Es muss auch ein Setter existieren:
Delphi-Quellcode:
TCustomMyComp = class(TCustomControl)
  private
    FItems: TMyItemList;
    ...
  public
    ...
    property Items: TMyItemList read FItems write FItems; // incl. write, nicht wie im 1. Beitrag ohne
end;

HeZa 16. Apr 2010 15:40

Re: TCollection speichert nicht im DFM, was fehlt?
 
@Andreas:

Zitat:

Zitat von Andreas L.
@Heza: So sollte der constructor von TCollection nicht überschrieben werden

Doch, so sollte das gemacht werden (siehe z.B. THeaderSection in ComCtrls).

Zitat:

Zitat von Andreas L.
Und da liegt auch nicht der Fehler ;-)

Das ist allerdings richtig. :-)

Es liegt wohl eher daran das er in der Komponente seine Collection Eigenschaft nicht im published-Teil stehen hat.

Mit dem folgenden Source habe ich auf jedenfall erfolgreich eine Komponente mit Collection-Eigenschaft programmiert (getestet unter D2010, sollte aber keine Rolle spielen)

Delphi-Quellcode:
unit MyComponents;

interface

uses
  SysUtils, Classes;

type
  TMyCollectionItem = class(TCollectionItem)
  private
    FData: String;
  public
    procedure Assign(Source: TPersistent); override;
  published
    property Data: String read FData write FData;
  end;

  TMyCollection = class(TCollection)
  private
    FOwner: TComponent;
    function GetItems(Index: Integer): TMyCollectionItem;
    procedure SetItems(Index: Integer; Value: TMyCollectionItem);
  protected
    function GetOwner: TPersistent; override;
  public
    constructor Create(Owner: TComponent);
    function Add: TMyCollectionItem;
    property Items[Index: Integer]: TMyCollectionItem read GetItems write SetItems; default;
  end;

  TMyComponent = class(TComponent)
  private
    FItems: TMyCollection;
    procedure SetItems(const Value: TMyCollection);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Items: TMyCollection read FItems write SetItems;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TMyComponent]);
end;

{ TMyCollectionItem }

procedure TMyCollectionItem.Assign(Source: TPersistent);
begin
  if Source is TMyCollectionItem then
    Data := TMyCollectionItem(Source).data
  else
    inherited;
end;

{ TMyCollection }

constructor TMyCollection.Create(Owner: TComponent);
begin
  inherited Create(TMyCollectionItem);
  FOwner := Owner;
end;

function TMyCollection.Add: TMyCollectionItem;
begin
  Result := inherited Add as TMyCollectionItem;
end;

function TMyCollection.GetItems(Index: Integer): TMyCollectionItem;
begin
  Result := GetItem(Index) as TMyCollectionItem;
end;

function TMyCollection.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

procedure TMyCollection.SetItems(Index: Integer; Value: TMyCollectionItem);
begin
  SetItem(Index, Value);
end;

{ TMyComponent }

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  FItems := TMyCollection.Create(self);
end;

destructor TMyComponent.Destroy;
begin
  FreeAndNil(FItems);
  inherited;
end;

procedure TMyComponent.SetItems(const Value: TMyCollection);
begin
  FItems := Value;
end;

end.
Ciao HeZa

HeZa 16. Apr 2010 15:44

Re: TCollection speichert nicht im DFM, was fehlt?
 
Zitat:

Zitat von RSE
Lösung: Die Items-Property in TCustomMyComp darf nicht readonly sein. Es muss auch ein Setter existieren:

Wunderbar :-)

Delphi-Quellcode:
TCustomMyComp = class(TCustomControl)
  ...
  public
    ...
    property Items: TMyItemList read FItems write FItems; // incl. write, nicht wie im 1. Beitrag ohne
end;
Und die Eigenschaft Items, steht nicht im published Teil? Hmm...

Es würde mich auch noch interessieren, ob du GetOwner überschrieben hast?

Ciao Heinz Z.

RSE 16. Apr 2010 18:55

Re: TCollection speichert nicht im DFM, was fehlt?
 
In TCustomMyComp steht es im public, aber in TMyComp ist es dann published ;-)

TMyItem.GetOwner ist auch überschrieben, hatte ich vergessen mit hinzuschreiben hier. Ich konnte auch den Konstruktor von TMyItemList ändern und wenn ich mich nicht irre (Quelltext liegt auf Arbeit) Items als default deklarieren. Ebenso konnte ich die einfache Add-Methode streichen. Delphi 5 sagt auch nichts wegen überladen. Ich werd Montag mal ausprobieren, ob das Add überladen oder verdeckt ist und schreibe das dann hier noch mal rein.

Ich wünsche allen ein schönes Wochenende!

RSE 20. Apr 2010 07:04

Re: TCollection speichert nicht im DFM, was fehlt?
 
Sorry, ich hatte gestern vergessen nachzusehen...

Es ist wie ich schrieb:
  • GetOwner ist überschrieben
  • Konstruktor ist geändert
  • Items ist default
  • Add ist mit einer komplexeren Variante mit Parametern verdeckt

Und die Komponente läuft.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:26 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz