首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法为TPersistent属性中的TCollection属性打开集合编辑器

无法为TPersistent属性中的TCollection属性打开集合编辑器
EN

Stack Overflow用户
提问于 2011-08-08 17:55:46
回答 1查看 2.3K关注 0票数 2

我有我的自定义集合属性,当它是我的组件的直接成员时,它工作得很好。

但是我想将集合属性移动到我的组件中的TPersistent属性。现在问题来了,它不工作了:双击对象检查器中的集合属性通常会打开集合编辑器,但现在不再打开了。

首先,我应该向TPersistent属性的构造器传递什么?

代码语言:javascript
复制
TMyCollection = class(TCollection)
  constructor Create(AOwner: TComponent); // TMyCollection constuctor
  ...

我不能通过Self,所以我应该通过我的持久化所有者吗?

代码语言:javascript
复制
constructor TMyPersistent.Create(AOwner: TComponent);
begin
  inherited Create;
  fOwner := AOwner;
  fMyCollection := TMyCollection.Create(AOwner); // hmmm... doesn't make sense
end;

我想我漏掉了什么。如果需要更多代码,请评论这篇文章。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-08-08 18:20:18

TCollection的构造函数不需要TComponent,而需要TCollectionItemClass。

您的集合现在是TPersistent属性的成员,而不是组件的直接成员,这对构造函数没有任何影响。

更新

不同之处在于所有权,但在TPersistent级别,应该由正确的GetOwner实现来管理

GetOwner返回对象的所有者。GetNamePath方法使用GetOwner来查找持久对象的所有者。GetNamePath和GetOwner是在TPersistent中引入的,因此诸如集合之类的子体可以出现在对象检查器中。

您必须告诉集成开发环境,您的TCollection属性归TPersistent属性所有,而后者又归组件所有。

关于这个实现,The tutorial you are using有几个错误:

  • 集合的所有者被声明为TComponent,它应该是TPersistent,
  • GetOwner不是为TPersistent属性类实现的,
  • 教程末尾显示的说明TPersistent属性应该从TComponent继承的修复是完全错误的;或者更好地说:这是不实现GetOwner的解决方法。

它应该是这样的:

代码语言:javascript
复制
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.

但是我可以说,您也可以继承TOwnedCollection,这使得TMyCollection的使用和声明变得更加简单:

代码语言:javascript
复制
  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;
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6980401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档