The collection editor does not open for the TCollection property in the TPersistent property

I have my own custom collection property that works great when it is a direct member of my component.

But I want to transfer the collection property to the TPersistent property inside my component. And now the problem arises, it does not work: double-clicking on the collection property in the object inspector usually opens the collection editor, but it does not work anymore.

Fist of all - what should I pass to the TPersistent property constructor?

TMyCollection = class(TCollection) constructor Create(AOwner: TComponent); // TMyCollection constuctor ... 

I can’t get past the self, so do I have to pass on my insistent owner?

 constructor TMyPersistent.Create(AOwner: TComponent); begin inherited Create; fOwner := AOwner; fMyCollection := TMyCollection.Create(AOwner); // hmmm... doesn't make sense end; 

I think I'm missing something. If more code is required, just comment on this post.

Da visualizationz

+2
delphi delphi-2010 tpersistent
source share
1 answer

The TCollection constructor does not need a TComponent, but a TCollectionItemClass.

Now your collection, which is a member of the TPersistent property, instead of a direct component element, has no meaning for the constructor.


Update

What is the difference is ownership, but then at the TPersistent level, which must be managed by the correct GetOwner implementation:

GetOwner returns the owner of the object. GetOwner is used by the GetNamePath method to find the owner of a permanent object. GetNamePath and GetOwner are introduced into TPersistent, so descendants such as collections can appear in the object inspector.

You must tell the IDE that your TCollection property belongs to the TPersistent property, which in turn belongs to the component.

There are a few errors in the tutorial that you use regarding this implementation:

  • The owner of the collection is declared as a TComponent, which must be TPersistent,
  • GetOwner is not implemented for the TPersistent property class and
  • The fix shown at the end of the tutorial, which states that the TPersistent property should inherit from TComponent, is simply wrong; or more beautifully said: rather, it is a workaround for not implementing GetOwner.

Here's how it should look:

 unit MyComponent; interface uses Classes, SysUtils; type TMyCollectionItem = class(TCollectionItem) private FStringProp: String; protected function GetDisplayName: String; override; public procedure Assign(Source: TPersistent); override; published property StringProp: String read FStringProp write FStringProp; end; TMyCollection = class(TCollection) private FOwner: TPersistent; function GetItem(Index: Integer): TMyCollectionItem; procedure SetItem(Index: Integer; Value: TMyCollectionItem); protected function GetOwner: TPersistent; override; public constructor Create(AOwner: TPersistent); function Add: TMyCollectionItem; function Insert(Index: Integer): TMyCollectionItem; property Items[Index: Integer]: TMyCollectionItem read GetItem write SetItem; end; TMyPersistent = class(TPersistent) private FOwner: TPersistent; FCollectionProp: TMyCollection; procedure SetCollectionProp(Value: TMyCollection); protected function GetOwner: TPersistent; override; public procedure Assign(Source: TPersistent); override; constructor Create(AOwner: TPersistent); destructor Destroy; override; published property CollectionProp: TMyCollection read FCollectionProp write SetCollectionProp; end; TMyComponent = class(TComponent) private FPersistentProp: TMyPersistent; procedure SetPersistentProp(Value: TMyPersistent); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property PersistentProp: TMyPersistent read FPersistentProp write SetPersistentProp; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TMyComponent]); end; { TMyCollectionItem } procedure TMyCollectionItem.Assign(Source: TPersistent); begin if Source is TMyCollectionItem then FStringProp := TMyCollectionItem(Source).FStringProp else inherited Assign(Source); end; function TMyCollectionItem.GetDisplayName: String; begin Result := Format('Item %d',[Index]); end; { TMyCollection } function TMyCollection.Add: TMyCollectionItem; begin Result := TMyCollectionItem(inherited Add); end; constructor TMyCollection.Create(AOwner: TPersistent); begin inherited Create(TMyCollectionItem); FOwner := AOwner; end; function TMyCollection.GetItem(Index: Integer): TMyCollectionItem; begin Result := TMyCollectionItem(inherited GetItem(Index)); end; function TMyCollection.GetOwner: TPersistent; begin Result := FOwner; end; function TMyCollection.Insert(Index: Integer): TMyCollectionItem; begin Result := TMyCollectionItem(inherited Insert(Index)); end; procedure TMyCollection.SetItem(Index: Integer; Value: TMyCollectionItem); begin inherited SetItem(Index, Value); end; { TMyPersistent } procedure TMyPersistent.Assign(Source: TPersistent); begin if Source is TMyPersistent then CollectionProp := TMyPersistent(Source).FCollectionProp else inherited Assign(Source); end; constructor TMyPersistent.Create(AOwner: TPersistent); begin inherited Create; FOwner := AOwner; FCollectionProp := TMyCollection.Create(Self); end; destructor TMyPersistent.Destroy; begin FCollectionProp.Free; inherited Destroy; end; function TMyPersistent.GetOwner: TPersistent; begin Result := FOwner; end; procedure TMyPersistent.SetCollectionProp(Value: TMyCollection); begin FCollectionProp.Assign(Value); end; { TMyComponent } constructor TMyComponent.Create(AOwner: TComponent); begin inherited Create(AOwner); FPersistentProp := TMyPersistent.Create(Self); end; destructor TMyComponent.Destroy; begin FPersistentProp.Free; inherited Destroy; end; procedure TMyComponent.SetPersistentProp(Value: TMyPersistent); begin FPersistentProp.Assign(Value); end; end. 

But can I say that you can also inherit from TOwnedCollection , which greatly simplifies the use and declaration of TMyCollection:

  TMyCollection = class(TOwnedCollection) private function GetItem(Index: Integer): TMyCollectionItem; procedure SetItem(Index: Integer; Value: TMyCollectionItem); public function Add: TMyCollectionItem; function Insert(Index: Integer): TMyCollectionItem; property Items[Index: Integer]: TMyCollectionItem read GetItem write SetItem; end; 
+8
source share

All Articles