可能吗? TCollection后代实现具有任意内容的TPanel容器的存储

时间:2010-09-27 14:29:06

标签: delphi components delphi-2010 tcollection tcollectionitem

我是Delphi组件开发的新手,因此想知道,是否可以实现我的任务。

我需要创建一个基于TScrollBox的可视化组件(用户控件),它将代表一堆TPanel,所有面板将在TScrollBox内部对齐为“Top”,并且可以具有不同的高度。它必须充当TCollection(添加,删除。重新排序),并且必须允许用户在设计时将其他控件添加到这些面板中。

我为组件创建了这些类:

type
  TPanelsGrid = class;

  TPanelsGridItem = class(TCollectionItem)
  private
    FPanel: TPanel;
    procedure SetPanel(Value: TPanel);
    function GetGrid: TPanelsGrid;
  protected
    function GetDisplayName: string; override;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    // This is my TPanel object that should be used at designtime
    // I thought "stored True" will serialize it automatically but I was wrong
    property Panel: TPanel read FPanel write SetPanel stored True; 
  end;

  TPanelsGridItems = class(TCollection)
  private
    FPanelsGrid: TPanelsGrid;
  protected
    function GetItem(Index: Integer): TPanelsGridItem;
    procedure SetItem(Index: Integer; Value: TPanelsGridItem);

    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    property EditorsGrid: TPanelsGrid read FPanelsGrid;
    property Items[Index: Integer]: TPanelsGridItem
      read GetItem write SetItem; default;

    constructor Create(PanelsGrid: TPanelsGrid);
    function Add: TPanelsGridItem;
    procedure Delete(Index: Integer);
  end;

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

这个组件在设计时工作正常,我可以在堆栈中添加 - 删除面板,当我在任何面板上放下一些控件(例如TCheckbox)时,它显示为“由该面板拥有”:例如:我无法将此复选框拖出面板。

但是此复选框未存储在DFM文件中,并且未显示在“结构”窗口中。

我想必须对TPanel的内容进行一些手动序列化 - 反序列化,但我不知道如何做到这一点。在Internet上找不到任何示例。如果可以实现这样的话,Plase会给我一些指导。

加成

这是在将3个面板添加到网格后我的DFM文件片段的样子:

  object PanelsGrid1 : TPanelsGrid 
    Left = 8
    Top = 8
    Width = 536
    Height = 382
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 0
    Items = <
      item
      end
      item
      end
      item
      end>
  end

正如您所看到的,所有项目都是空的,但我在那里放了一个复选框和单选按钮进入第3项。

3 个答案:

答案 0 :(得分:1)

毕竟我决定放弃使用TCollection,因为在测试DefineProperties方法时我遇到了一致的IDE崩溃。我认为TCollection并不是为这样的任务而设计的。

我在控制ExtCtrls.TCustomCategoryPanelGroup内部的Delphi源代码中创建了一个适当的实现。它维护了可以在设计时和运行时添加或删除的面板堆栈。我使用TCustomCategoryPanelGroup和TCustomCategoryPanel的源代码创建了自己的类,它可以正常工作。

答案 1 :(得分:0)

我认为您可以查看TMS Poly List control

  

TMS Advanced Poly List组件   提供一个非常多才多艺的   灵活的架构来创造   几乎任何可能的项目清单   在用户界面中。这是可以看到的   通常但不限于新的   Office 2010应用程序菜单。相反   到大多数用户界面列表控件,   列表由项目组成   相同类型或项目的集合   相同的类型,TMS Advanced Poly   列表组件可以包含多态   项目。所有物品都需要下降   来自基类TCustomItem和   可以添加任何继承的项目。 TMS   高级Poly List组件来了   有一大堆预建列表   项目,但自定义项目类可以   添加任何一个降序   TCustomItem基类或任何一个   已经提供的课程。有   项目类显示为列表部分   item,带HTML格式的文本项,   带有按钮的文本项,带有的项   展开/折叠行为,项目   图像等等。物品可以   在多态信息列表中添加了   设计时间,设计时间丰富   编辑器,并在运行时通过代码。

答案 2 :(得分:0)

确保您的子面板有名称。您可以覆盖TCollection.Notify,如果Action是cnAdded,请确保该面板有名称。