Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

TCollection not saving items

Status
Not open for further replies.

djjd47130

Programmer
Nov 1, 2010
480
US
I have made a few TCollection sets before, and never ran across this problem before, and it has me puzzled.

When I open the collection editor on my component, I am able to add new collection items, set their properties, etc. Even when I close the property editor and re-open it, my collection items are there and have all the values properly.

However, then I save my form, close the form, re-open it, go back to that component and open the collection editor, and those items are gone.

Here's my code for these collections:

Code:
  //Event triggered when a specific command has been executed
  TJDScktSvrCmdEvent = procedure(Sender: TObject; Socket: TJDServerClientSocket;
    const Data: TStrings) of object;

  //Represents a collection of different possible commands
  TSvrCommands = class(TCollection)
  private
    fOwner: TJDServerSocket;
    function GetItem(Index: Integer): TSvrCommand;
    procedure SetItem(Index: Integer; Value: TSvrCommand);
  public
    constructor Create(ASocket: TJDServerSocket);
    destructor Destroy;
    procedure DoCommand(const Socket: TJDServerClientSocket; const Cmd: Integer; const Data: TStrings); 
    function Add: TSvrCommand;
    property Items[Index: Integer]: TSvrCommand read GetItem write SetItem;
  end;

  //Represents a collection item of a specific command which can be executed
  TSvrCommand = class(TCollectionItem)
  private
    fName: String; //Unique Name - user may change to any string, as long as it's not already being used
    fID: Integer; //Unique ID - user may change to any integer, as long as it's not already being used
    fOnCommand: TJDScktSvrCmdEvent;
    //Property Control
    procedure SetID(Value: Integer); 
    procedure SetName(Value: String);
  protected
    function GetDisplayName: String; override;
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
  published
    property ID: Integer read fID write SetID;
    property Name: String read fName write SetName;
    property OnCommand: TJDScktSvrCmdEvent read fOnCommand write fOnCommand;
  end;

And the implementation:

Code:
{ TSvrCommands }

function TSvrCommands.Add: TSvrCommand;
begin
  Result:= TSvrCommand(inherited Add);
end;

constructor TSvrCommands.Create(ASocket: TJDServerSocket);
begin
  inherited Create(TSvrCommand);
  Self.fOwner:= ASocket;
end;

destructor TSvrCommands.Destroy;
begin
  inherited Destroy;
end;

//Loops through commands to find the one it needs to execute
procedure TSvrCommands.DoCommand(const Socket: TJDServerClientSocket;
  const Cmd: Integer; const Data: TStrings);
var
  X: Integer;
  C: TSvrCommand;
  F: Bool;
begin
  F:= False;
  for X:= 0 to Self.Count - 1 do begin
    C:= GetItem(X);
    if C.ID = Cmd then begin
      F:= True;
      if assigned(C.fOnCommand) then
        C.fOnCommand(Self, Socket, Data);
      Break;
    end;
  end;
  if not F then begin
    //Command not found - raise exception

  end;
end;

function TSvrCommands.GetItem(Index: Integer): TSvrCommand;
begin
  Result:= TSvrCommand(inherited Items[Index]);
end;

procedure TSvrCommands.SetItem(Index: Integer; Value: TSvrCommand);
begin
  inherited Items[Index]:= Value;
end;

{ TSvrCommand }

procedure TSvrCommand.Assign(Source: TPersistent);
begin
  inherited;

end;

constructor TSvrCommand.Create(Collection: TCollection);
begin
  inherited Create(Collection);
  //Not creating anything
end;

destructor TSvrCommand.Destroy;
begin
  //Not freeing anything
  inherited Destroy;
end;

function TSvrCommand.GetDisplayName: String;
begin
  Result:= Name;
end;

procedure TSvrCommand.SetID(Value: Integer);
begin
  fID:= Value;
end;

procedure TSvrCommand.SetName(Value: String);
begin
  fName:= Value;
end;


JD Solutions
 
However, then I save my form, close the form, re-open it, go back to that component and open the collection editor, and those items are gone.

The one glaring omission I see is the following:

Code:
 TMyCollection = class(TCollection)
...
    protected
      function GetOwner: TPersistent; override;
...
    end;

function TMyCollection.GetOwner: TPersistent;
begin
  Result := FOwner;
end;

In fact, it could be a difference between Delphi 3 (what I'm using) and 7 on this, but D3 complained pretty loudly when I tried to hit the property editor on this without having the above defined.

HTH.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Holy cow, I even had exactly that in my code from the very beginning, and removed it thinking that's what was causing the problem. I guess there must have been two issues, while one issue *may* have been fixed, this issue of the GetOwner override I rather reversed.

As far as assigning an event handler to each collection item, I got it figured out without needing to assign a name (it scared be because upon trying to create a new event handler by double clicking the event property, it gave me an error that it can't create an event handler for an unnamed object.).

Which in turn kind of eliminates the need to accomplish my other thread related to naming the collection items. It would be a nifty little project, but for now, I can make do without.

Thanks again.

**hitting self in head for missing this**


JD Solutions
 
Now that I had the time to sit down and look at it, I have realized that my issue was I was not settings this fOwner. Simple mistake - in the constructor method, I was not setting fOwner:= AOwner;

JD Solutions
 
That was a dyslexic moment on my last post :p... Actually I was wrong about that, it was part of the reason but I didn't test it entirely (I didn't completely close the form and re-open to confirm it saved). Now I really did find the problem. Upon declaring the implementation of the collection from the component's published properties, I only had the read assigned to the property, not the write. Therefore, when the component was created, it did not assign any of the saved items. So, it went from...

Code:
property Commands: TJDServerSocketCommands read fCommands;

to...

Code:
property Commands: TJDServerSocketCommands read fCommands write fCommands;


JD Solutions
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top