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
. PropiedadGrid
no 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.