Wie eine TCollection-Eigenschaft einer Unterkomponente, z. die Columns-Eigenschaft eines eingebetteten TDBGrid

Ich habe versucht, mich auf einen MCVE-Code zu beschränken, den mir der Autor eines anderen q geschickt hat, um ein Problem mit einer benutzerdefinierten Komponente zu veranschaulichen.

Die Komponente ist einfach ein TPanel-Nachkomme, der ein eingebettetes TDBGrid enthält. Meine Version der Quelle und ein Testprojekt finden Sie weiter unten.

Das Problem ist, dass, wenn das eingebettete DBGrid mit persistenten Spalten erstellt wurde, beim erneuten Öffnen seines Testprojekts in der IDE eine Ausnahme ausgelöst wird

Fehler beim LesenTColumn.Grid.Expanded. EigentumGridist nicht vorhanden

Ausführen desStreamie @ -Methode des Testprojekts zeigt, wie dieses Problem auftritt:

Zum Vergleich habe ich auch ein normales TDBGrid, DBGrid1, in meinem Formular. Während die Spalten dieses DBGrid1 als @ gestreamt werd

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

die Spalten des eingebetteten Gitters werden wie folgt gestreamt

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

Es ist offensichtlich dasGrid Präfix vonGrid.Expanded und die anderen Spalteneigenschaften, die das Problem verursachen.

Ich stelle mir vor, dass das Problem damit zusammenhängt, dass DBGridColumns ein Nachkomme von TCollection ist und das eingebettete Raster nicht das Objekt der obersten Ebene in DFM ist.

Meine Frage ist: Wie soll der Code vonTMyPanel so geändert werden, dass die Spalten des Rasters korrekt gestreamt werden?

Komponentenquelle:

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.

Test Projektquelle:

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.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage