AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi TCollection speichert nicht im DFM, was fehlt?
Thema durchsuchen
Ansicht
Themen-Optionen

TCollection speichert nicht im DFM, was fehlt?

Ein Thema von RSE · begonnen am 16. Apr 2010 · letzter Beitrag vom 17. Mär 2013
Antwort Antwort
Seite 1 von 2  1 2      
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#1

TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 13:57
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?
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#2

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 15:04
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):

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
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#3

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 15:08
Ich sehe gerade noch, die Funktion Add (ohne Parameter) sollte auch den Rückgabetyp TMyItem haben. Also so:

function Add: TMyItem; overload; Viel Spaß
Ciao HeZa
  Mit Zitat antworten Zitat
Andreas L.
(Gast)

n/a Beiträge
 
#4

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 15:11
@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:
  property Items[Index: Integer]: TMyItem read GetItem write SetItem;
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#5

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 15:30
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.
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#6

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 16:11
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;
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#7

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 16:40
@Andreas:

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 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
  Mit Zitat antworten Zitat
HeZa

Registriert seit: 4. Nov 2004
Ort: Dortmund
182 Beiträge
 
Delphi 10 Seattle Professional
 
#8

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 16:44
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.
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#9

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 16. Apr 2010, 19:55
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!
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#10

Re: TCollection speichert nicht im DFM, was fehlt?

  Alt 20. Apr 2010, 08:04
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.
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  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 03:02 Uhr.
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