我一直在尝试将另一个问题的作者给我的代码转化为MCVE格式,以说明自定义组件存在的问题。
该组件仅是一个TPanel派生类,其中包含一个嵌入的TDBGrid。下面是源代码和测试项目的版本。
问题在于,如果嵌入的DBGrid使用持久性列创建,则在重新打开IDE中的测试项目时,会引发异常。 执行测试项目的Stream方法可以显示出问题的原因:
为了进行比较,我的表单上还有一个普通的TDBGrid,名为DBGrid1。而这个DBGrid1的列被流化为...
嵌入式网格的列会像这样流式传输。
显然是
我想问题与DBGridColumns是TCollection的后代以及嵌入式网格不是DFM中的顶层对象有关。
我的问题是:应该如何修改
组件源码:
该组件仅是一个TPanel派生类,其中包含一个嵌入的TDBGrid。下面是源代码和测试项目的版本。
问题在于,如果嵌入的DBGrid使用持久性列创建,则在重新打开IDE中的测试项目时,会引发异常。 执行测试项目的Stream方法可以显示出问题的原因:
为了进行比较,我的表单上还有一个普通的TDBGrid,名为DBGrid1。而这个DBGrid1的列被流化为...
Columns = <
item
Expanded = False
FieldName = 'ID'
Visible = True
end
[...]
嵌入式网格的列会像这样流式传输。
Grid.Columns = <
item
Grid.Expanded = False
Grid.FieldName = 'ID'
Grid.Visible = True
end
[...]
显然是
Grid.Expanded
和其他列属性的Grid
前缀导致了问题。我想问题与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.
TDBGrid
始终成为Panel的子控件吗?如果是这样,那么Panel的构造函数应该有一个FGrid.Parent := Self;
语句,并且应该完全删除SetParent()
重载。 - Remy Lebeau