componentsdelphi-xe5

Properties of published nested components are not saved, events are not visible in object inspector


I created a component with following contents:

TEditLine = class(TCustomControl)
strict private
  FCaptionLabel: TLabel;
  FUnitLabel: TLabel;
  FEdit: TMyEdit;
end;

Then I started to propagate necessary properties of nested components by creating of corresponding getter/setter pairs.

Suddenly I thought, it may be easier to publish these nested components themselves as read-only properties so that when some new property or method gets introduced to one of these components, no changes in container component interface are required:

TEditLine = class(TCustomControl)
strict private
  FCaptionLabel: TLabel;
  FUnitLabel: TLabel;
  FEdit: TMyEdit;
published
  property CaptionLabel: TLabel read FCaptionLabel;
  property UnitLabel: TLabel read FUnitLabel;
  property Edit: TMyEdit read FEdit;
end;

When I put the component on a form, I see CaptionLabel, UnitLabel and Edit in Object Inspector, but that is all I can achieve.

Is it generally a good idea to do so? How I solve the two issues listed above?


Solution

  • TComponent-based properties are treated as references to external components by default, unless you call SetSubComponent(True) on the objects that back them, eg:

    TEditLine = class(TCustomControl)
    strict private
      FCaptionLabel: TLabel;
      FUnitLabel: TLabel;
      FEdit: TMyEdit;
    public
      constructor Create(AOwner: TComponent); override;
    published
      property CaptionLabel: TLabel read FCaptionLabel;
      property UnitLabel: TLabel read FUnitLabel;
      property Edit: TMyEdit read FEdit;
    end;
    
    ... 
    
    constructor TEditLine.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ...
      FCaptionLabel := TLabel.Create(Self);
      FCaptionLabel.Parent := Self;
      FCaptionLabel.SetSubComponent(True); // <-- ADD THIS
      ...
      FUnitLabel := TLabel.Create(Self);
      FUnitLabel.Parent := Self;
      FUnitLabel.SetSubComponent(True); // <-- ADD THIS
      ...
      FEdit := TMyEdit.Create(Self);
      FEdit.Parent := Self;
      FEdit.SetSubComponent(True); // <-- ADD THIS
      ...
    end;