组件流和自动源文件更新

时间:2010-10-15 16:53:35

标签: delphi

我首先要说的是,我以前在组件设计方面的经验仅限于在一个非常标准的视觉控件集合中修复小错误。

我目前正在开发一个项目,该项目使用TPersistent后代树来定义,存储和检索数据。这棵树的顶部是TComponent的后代。它有一个已发布的属性,是TCollection的后代。这是结构的简化:

TMyComponent = class(TComponent)
private
  FMyCollection: TMyCollection;
published
  property Items: TMyCollection read FMyCollection write FMyCollection;
end;

TMyCollection = class(TCollection)
protected
  procedure SetItem(index: integer; val: TCompositeItem);
  function GetItem(index: integer): TCompositeItem;
public
  property Items[index: integer]: TCompositeItem read GetItem write SetItem; default;
end;

TCompositeItem = class(TCollectionItem)
private
  FMyCollection: TMyCollection;
published
  property Items: TMyCollection read FMyCollection write FMyCollection;
end;

至少有十几个TCompositeItem的后代。如果要将新项添加到树中某个节点的集合中,请调出上下文菜单,然后单击“添加项”。这将创建一个新项目,然后您必须使用Object Inspector进一步将其定义为TCompositeItem的众多后代中的一个。

这个效果相对较好。问题是设计器中树的更改不会反映在关联的源文件中。为了解决这个问题,我的前任添加了一些同步代码,用于在.dfm中的树中重新创建.pas文件中的声明。要正确同步您在dfm中保存更改的所有内容,请双击表单上的组件(触发同步代码),然后再次保存。此外,每个编辑会话只能执行一次同步,否则会收到提示,告诉您关闭表单,重新打开,然后执行同步。如果您忘记遵循此过程,则会在运行时发生各种奇怪的行为。它有点尴尬,但它有效。

我想做的事情是设计器中的更改会在缓存的源文件中自动更新,然后在开发人员点击保存时正常保存,从而无需进行尴尬的三步同步。 / p>

这是正常控​​制的工作方式,所以我不确定为什么它不适用于这个。我有一种直觉,认为原因可能与集合中每个项目的最终类有关,直到它在设计师中创建之后才被确定。有什么建议吗?

更新

经过进一步调查,看起来同步代码做了两件事:

  1. 编辑表单的类定义,为树中的每个节点添加已发布的字段。
  2. 编辑名为InitializeComponents的过程,该过程将每个节点分配给其中一个已发布的字段。

1 个答案:

答案 0 :(得分:0)

DFM流系统不是为处理存储在单个TCollection中的多个TCollectionItem后代类而设计的。您必须为TCollection禁用本机流,然后手动流式传输所有项目,以便您可以将每个项目的ClassName存储到DFM中,然后将其读回并在加载时手动实例化正确的TCollectionItem类。

至于对源代码进行更新,您需要在单独的设计时组件编辑器中处理它,而不是在组件本身中处理。通常,您将注册一个TComponentEditor类,该类在设计时将菜单项添加到主组件的右键单击上下文菜单中。调用时,该菜单项可以根据需要提示用户输入类类型,然后通过调用IDesigner.CreateComponent()方法对其进行实例化并将其引用添加到组件的父窗体中。但是,这意味着集合项必须是TComponent后代而不是TCollectionItem后代。

您尝试实施的系统与TFields集合的工作原理非常相似。但是如果你仔细观察它,它根本不是基于TCollection和TCollectionItem。 TField直接从TComponent派生,TFields直接从TObject派生。