Cómo transmitir correctamente una propiedad TCollection de un subcomponente, p. la propiedad Columnas de una TDBGrid incrustada

He estado tratando de reducir a MCVE un código que el autor de otro q me envió para ilustrar un problema con un componente personalizado.

El componente es simplemente un descendiente de TPanel que incluye un TDBGrid incorporado. Mi versión de su fuente y un proyecto de prueba están a continuación.

El problema es que si el DBGrid incrustado se ha creado con columnas persistentes, cuando su proyecto de prueba se vuelve a abrir en el IDE, se genera una excepción

Error de lecturaTColumn.Grid.Expanded. PropiedadGridno existe.

Ejecutando elStream El método del proyecto de prueba muestra cómo surge este problema:

Para fines de comparación, también tengo un TDBGrid normal, DBGrid1, en mi formulario. Mientras que las columnas de este DBGrid1 se transmiten como

Columns = <
  item
    Expanded = False
    FieldName = 'ID'
    Visible = True
  end
[...]

las columnas de la cuadrícula incrustada se transmiten así

Grid.Columns = <
  item
    Grid.Expanded = False
    Grid.FieldName = 'ID'
    Grid.Visible = True
  end
[...]

Obviamente es elGrid prefijo deGrid.Expanded y las otras propiedades de columna que están causando el problema.

Me imagino que el problema tiene algo que ver con el hecho de que DBGridColumns es un descendiente de TCollection y que la cuadrícula incrustada no es el objeto de nivel superior en el DFM.

Mi pregunta es: ¿cómo debe ser el código deTMyPanel ser modificado para que las columnas de la cuadrícula se transmitan correctamente?

Fuente de componentes:

unit MAGridu;

interface

uses
  Windows, SysUtils, Classes, Controls, ExtCtrls, DBGrids;

type
  TMyPanel = class(TPanel)
  private
    FGrid : TDBGrid;
  public
    constructor Create(AOwner : TComponent); override;
  published
    property Grid : TDBGrid read FGrid;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TMyPanel]);
end;

constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FGrid := TDBGrid.Create(Self);
  FGrid.SetSubcomponent(True);
  FGrid.Parent := Self;
end;

end.

Probar fuente del proyecto:

type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    CDS1: TClientDataSet;
    DataSource1: TDataSource;
    MyPanel1: TMyPanel;
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure Stream;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Stream;
end;

procedure TForm1.Stream;
//  This method is included as an easy way of getting at the contents of the project's
//  DFM.  It saves the form to a stream, and loads it into a memo on the form.
var
  SS : TStringStream;
  MS : TMemoryStream;
  Writer : TWriter;
begin
  SS := TStringStream.Create('');
  MS := TMemoryStream.Create;
  Writer := TWriter.Create(MS, 4096);

  try
    Writer.Root := Self;
    Writer.WriteSignature;
    Writer.WriteComponent(Self);
    Writer.FlushBuffer;
    MS.Position := 0;
    ObjectBinaryToText(MS, SS);
    Memo1.Lines.Text := SS.DataString;
  finally
    Writer.Free;
    MS.Free;
    SS.Free;
  end;
end;
end.

procedure TForm1.FormCreate(Sender: TObject);
var
  Field : TField;
begin
  Field := TIntegerField.Create(Self);
  Field.FieldName := 'ID';
  Field.FieldKind := fkData;
  Field.DataSet := CDS1;

  Field := TStringField.Create(Self);
  Field.FieldName := 'Name';
  Field.Size := 20;
  Field.FieldKind := fkData;
  Field.DataSet := CDS1;

  CDS1.CreateDataSet;
  CDS1.InsertRecord([1, 'One']);

end;

end.

Respuestas a la pregunta(2)

Su respuesta a la pregunta