I'm a french user of Delphi 2010 so please excuse my bad english.
I've created a control from a TCustomControl. This control have a TOwnedCollection populated by TCollectionItem descendant. Those Items have a published custom list property. This list is a list of couples of integers made by me. I've written a custom designtime editor for this property and it works perfectly. So now, I want to write the list data into the dfm and it becomes a bit harder.
Here is what I've done:
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;
The WriteListData procedure works perfectly and writes the values into the dfm. But when I try to load the Form, it always crashes and a dialog box tell me that there is an reading flow error on this property.
FList is created inside the constructor of the class.
Here is the .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
Error Messages (in french) :
1
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é
2
Erreur lors de la lecture de TPedroGraphLineCollectionItem.□□: la propriété □□ n'existe pas. Ignorer l'erreur et continuer ?Remarque: ceci peut provoquer la suppression de composants ou la perte de valeurs de propriété
Note: the '□' char is really displayed as this.
3
Erreur lors de la lecture de TPedroGraphLineCollectionItem.□□
4
Erreur lors de la lecture de PedroGraphLines1.Lines: 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é
5
Erreur à la création de la fiche : Erreur de lecture du flux.
Declaration of 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;
Where am I wrong ?
I think you miss the point of
DefineProperty
andpublished
They are mutually exclusive.published
means the VCL would store the real property by it's own means.DefineProperty
means there is no such real property but you would pretend like if there were some virtual one.what is your DFM ? May it be that 'PointList' is stored twice there - as the list and as the component ?
If so - you should select only one method of saving it ether one way or another, for example making the property PUBLIC rather than PUBLISHED.
Or maybe you may try to make non-clashing names like