我一直试图将另一个q的作者发给我的一些代码归结为MCVE
说明自定义组件的问题.
说明自定义组件的问题.
该组件只是一个TPanel后代,其中包含一个嵌入式TDBGrid.
我的源代码版本和测试项目如下.
问题是如果使用持久列创建嵌入式DBGrid,
当在IDE中重新打开其测试项目时,会引发异常
Error reading
TColumn.Grid.Expanded
. PropertyGrid
does not exist.
为了进行比较,我的表单上还有一个普通的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.
解决方法
似乎你无能为力.当您查看过程WriteCollectionProp(TWriter.WriteProperties的本地)时,您会看到在调用WriteCollection之前清除了FPropPath.
TDBGrid或更好的TCustomDBGrid的问题在于,集合被标记为存储为false,并且流被委托给DefineProperties,后者使用TCustomDBGrid.WriteColumns来完成工作.
检查该方法会发现,尽管它也调用了WriteCollection,但FPropPath的内容之前并未清除.由于FPropPath是一个私有字段,因此有些预期.
它仍然适用于标准用例的原因是,在编写时,FPropPath只是空的.
由于Delphi 10.1柏林的行为与Delphi 7相同,我建议仅与此示例一起提交QP报告.