自定义属性流读取错误

问题描述:

我是Delphi 2010的法语用户,请原谅我的英语不好。自定义属性流读取错误

我从TCustomControl创建了一个控件。此控件具有由TCollectionItem后裔填充的TOwnedCollection。 这些项目具有已发布的自定义列表属性。这个列表是我制作的一对整数列表。 我已经为此属性编写了一个自定义设计时编辑器,并且它完美地工作。 所以现在,我想将列表数据写入dfm中,并且变得有点困难。

这里是我做了什么:

TPedroGraphLineCollectionIem = class(TCollectionItem) 
    published 
    property PointList: TPedroIntegerCoupleList read FList write SetList 
     stored GetStored; 

... 
procedure TPedroGraphLineCollectionIem.DefineProperties(Filer: TFiler); 
begin 
    inherited; 
    //'PointList' : the property name 
    //FList.Count > 0 : Is the list empty ? 
    Filer.DefineProperty('PointList', ReadListData, WriteListData, 
    (FList.Count > 0)); 
end; 
... 
procedure TPedroGraphLineCollectionIem.ReadListData(Reader: TReader); 
var 
    Val1, Val2: Integer; 
begin 
    with Reader do 
    begin 
    ReadListBegin; 
    while not EndOfList do 
    begin 
     Val1 := ReadInteger; 
     Val2 := ReadInteger; 
     FList.AddCouple(Val1, Val2); 
    end; 
    ReadListEnd; 
    end; 
end; 
... 
procedure TPedroGraphLineCollectionIem.WriteListData(Writer: TWriter); 
var 
    I: Integer; 
begin 
    with Writer do 
    begin 
    WriteListBegin; 
    for I := 0 to Count - 1 do 
    begin 
     WriteInteger(FList[I].Value1); 
     WriteInteger(FList[I].Value2); 
    end; 
    WriteListEnd; 
    end; 
end; 

的WriteListData程序完美的作品和值写入DFM。但是当我尝试加载表单时,它总是崩溃,对话框告诉我这个属性有一个阅读流错误。

FList是在类的构造函数内部创建的。

这里是.DFM:

object MainFrm: TMainFrm 
    Left = 0 
    Top = 0 
    Caption = 'MainFrm' 
    ClientHeight = 425 
    ClientWidth = 689 
    Color = clBtnFace 
    ParentFont = True 
    OldCreateOrder = False 
    Position = poScreenCenter 
    OnCreate = FormCreate 
    OnDestroy = FormDestroy 
    PixelsPerInch = 96 
    TextHeight = 13 
    object PedroGraph1: TPedroGraph 
    Left = 120 
    Top = 136 
    Width = 313 
    Height = 209 
    TitleFont.Charset = DEFAULT_CHARSET 
    TitleFont.Color = clWindowText 
    TitleFont.Height = -11 
    TitleFont.Name = 'Tahoma' 
    TitleFont.Style = [] 
    Lines = < 
     item 
     LinePen.Color = clRed 
     PointList = (
      1 
      2 
      3 
      4) 
     end> 
    MarksFont.Charset = DEFAULT_CHARSET 
    MarksFont.Color = clWindowText 
    MarksFont.Height = -11 
    MarksFont.Name = 'Tahoma' 
    MarksFont.Style = [] 
    end 
end 

错误消息(法语):

Erreur lors de la lecture de TPedroGraphLineCollectionItem.PointList: Valeur de propriété incorrecte. Ignorer l'erreur et continuer ?Remarque: ceci peut provoquer la suppression de composants ou la perte de valeurs de propriété 

ERREUR的LOR德拉讲座德TPedroGraphLineCollectionItem □□:lapropriété□n'exist e pas。 Ignorer L'ERREUR等continuer雷马克:CECI peut provoquer LA抑制德composants欧拉perte德valeurs德propriété

注: '□' 字符确实显示这一点。

ERREUR的LOR德拉讲座德TPedroGraphLineCollectionItem□□

ERREUR的LOR德拉讲课德PedroGraphLines1.Lines:Valeur德propriétéincorrecte。 Ignorer L'ERREUR等continuer雷马克:CECI peut provoquer LA抑制去composants欧拉perte德valeurs德propriété

ERREUR点菜CRÉATION德拉平片:ERREUR德演讲杜通量。

TPedroIntegerCoupleList宣言:

TPedroIntegerCouple = record 
    Value1: Integer; 
    Value2: Integer; 
end; 

TPedroGenericList<T> = class(TList<T>) 
private 
    FOnChange: TNotifyEvent; 
    FUpdating: Boolean; 
protected 
    procedure Notify(const Item: T; Action: TCollectionNotification); override; 
    procedure DoChange; 
published 
public 
    constructor Create; 
    procedure SortCustom; virtual; abstract; 
    procedure Assign(const Source: TPedroGenericList<T>); 
    property OnChange: TNotifyEvent read FOnChange write FOnChange; 
end; 

TPedroIntegerCoupleList = class(TPedroGenericList<TPedroIntegerCouple>) 
private 
    function GetString: String; 
    procedure SetString(const Value: String); 
public 
    procedure SortCustom; override; 
    function AddCouple(const Value1, Value2: Integer): Integer; 
    procedure InsertCouple(const Index, Value1, Value2: Integer); 
    property AsString: String read GetString write SetString; 
end; 

我在哪里错了?

+0

转到项目选项,设置“使用调试DCU的”复选框,然后放在'TPedroGraphLineCollectionIem.ReadListData'以及'TPedroGraphLineCollectionIem断点。 DefineProperties'并调试DFM加载过程,就像调试其他一切一样。然后回来,说出哪一行确实会导致错误。包括复制异常的逐字文本(它可以从异常对话框复制粘贴为文本) –

+0

我试过这个,没有任何改变。当我谈论加载表单时,我的意思是在EDI中不使用断点。 – Pedrault

+0

您可以从另一个IDE运行一个IDE来调试组件 - 使用“主机应用程序”(这可能是IDE的另一个副本)阅读有关调试DLL和BPL(以及您的组件是BPL)的信息//也可逐字拷贝异常文本成为问题的适当部分,以及DFM源代码 - 仅仅让它们成为你的组件,而不需要其他东西//你也不需要在IDE中打开窗体来编译,运行和调试程序。只需调试它而不打开窗体。 –

我想你错过了点DefinePropertypublished 他们是互斥的。

  • published意味着VCL将通过它自己的方式存储不动产。
  • DefineProperty意味着没有这样的不动产,但你会假装像是有虚拟的。

什么是您的DFM?可能是'PointList'在那里存储了两次 - 作为列表和组件?

如果是这样 - 你应该只选择一种方法来保存它以某种方式,例如使属性PUBLIC而不是PUBLISHED。

或者,也许你可以尝试让非撞击的名字,像

property PointList: TPedroIntegerCoupleList read FList write SetList stored FALSE; 

Filer.DefineProperty('PointList_Virtual_DATA', .... 
+0

@Pedrault等错在哪里以及如何修复它? –

+0

是的!有用 !我修改了发布的属性存储为false,我已经定义了一个InternalPointList属性,它的工作原理!尽管如此,我已经想到了你所说的:发布的属性会自动写入。但是,使用WriteListData将数据正确写入dfm中......好了!非常感谢 !! – Pedrault

+0

@Pedrault您是否亲自阅读过DFM源代码?你没有在这里复制DFM,所以我不能为你做。我只能重复一遍:*你的DFM是什么? ?可能它是“PointList”被存储在那里的两倍 - 作为列表和作为组分* –