나는 MCVE의 코드를 작성하기 위해 다른 q의 작성자에게 나를 보내어 사용자 정의 컴포넌트의 문제점을 설명했다.하위 구성 요소의 TCollection 속성을 올바르게 스트리밍하는 방법 (예 : 포함 된 TDBGrid의 Columns 속성
구성 요소는 포함 된 TDBGrid를 포함하는 TPanel 하위 항목입니다. 소스의 나의 버전과 테스트 프로젝트가 아래에 있습니다.
문제는 포함 된 DBGrid를 영구 열이 생성 된 경우의 테스트 프로젝트가 IDE에서 다시 열릴 때, 는, 예외가 TColumn.Grid.Expanded
를 읽고
오류가 발생한다는 것입니다. 속성
Grid
이 존재하지 않습니다. 비교를 위해가, 나 또한 내 양식에 정상을 TDBGrid, DBGrid1를 가지고 : 테스트 프로젝트의
는Stream
방법을 실행
이 문제가 발생하는 방법을 보여줍니다. 이 DBGrid1의 열이
Columns = <
item
Expanded = False
FieldName = 'ID'
Visible = True
end
[...]
로 스트리밍되는 반면 포함 된 그리드의 열은 그것은 분명 Grid.Expanded
의 Grid
접두사와 문제의 원인이되는 다른 열 속성의이
Grid.Columns = <
item
Grid.Expanded = False
Grid.FieldName = 'ID'
Grid.Visible = True
end
[...]
같은 스트리밍됩니다.
문제는 DBGridColumns 이 TCollection 자손이며 DFM의 에있는 최상위 개체가 아니라는 사실과 관련이 있다고 생각합니다.
내 질문은 : 그리드의 열이 올바르게 스트리밍되도록 TMyPanel
코드를 수정해야합니까?
구성 요소 소스 :
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.
테스트 프로젝트 소스 :
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.
궁금한 점 : 왜 내재 된 그리드의 부모를 기본 MyPanel의 부모로 설정합니까? TMyPanel 동안. 그리드는 MyPanel에 부모 역할을합니다. 그런 식으로 머물러야하지 않습니까? –
@UweRaabe : 관심을 가져 주셔서 감사합니다. "TMyPanel 동안. 그리드는 MyPanel을 부모로 만듭니다." TMyPanel에서 빠져 나올 때 따라야하는지 잘 모르겠다. FGrid의 부모를 만드는 것은 아무런 이유없이 D7에서 Nil이므로 TMyPanel.SetParent에 할당하지 않으면 그리드가 보이지 않는다. – MartynA
@MartynA : TDBGrid를 항상 Panel의 하위 항목으로 만들려고하십니까? 그렇다면 Panel의 생성자는'FGrid.Parent : = Self;'문을 가져야하고'SetParent()'재정의는 완전히 제거되어야합니다. –