2005. november 2., szerda

How to use an item ID in a TTreeView as a unique number


Problem/Question/Abstract:

Is the ItemID a unique number for a node on the tree at hand only? Apparently this ID is not a true handle like for Windows that changes from time to time. I can run two instances of the same treeview object and the root node always has a number 5704360 and the second node always has the 5704400. These item IDs are cast to integers. I am trying to create an Outline editor, using a memo and a treeview and save the data in the memo to a stream along with some sort of unique identifier in order to be able to move nodes around without loosing a nodes assignment to a block of memo data. I thought about adding the itemid to the front of the block of data and remove it from the data while streaming the data back into the memo. Am I going in the wrong direction or what?

Answer:

I tend towards maintaining my own Ids and TreeNodes in a list:

TMemoSource = class(TPersisent)
private
  FId: Integer;
  FNode: TTreeNode;
  FStrings: TStringList;
  function GetStrings: TStrings;
  procedure SetStrings(Value: TStrings);
public
  property Id: Integer read FId write FId;
  property Node: TTreeNode read FNode write FNode;
  property Strings: TStrings read GetStrings write SetStrings;
end;

TMemoSources = class(TList)
private
  FNextId: Integer; {FNextId needs to be saved/initialised on application close/ run}
  function Get(Index: Integer): TMemoSource;
  procedure Put(Index: Integer; Item: TMemoSource);
public
  function AddItem: TMemoSource;
  property NextId: Integer read FNextId write FNextId;
  property Items[Index: Integer]: TMemoSource read Get write Put;
end;

function TMemoSources.AddItem: TAMemoSource;
var
  Item: TMemoSource;
begin
  Item := TMemoSource.Create;
  Inc(FNextId);
  Item.Id := FNextId;
  inherited Add(Item);
  Result := Item;
end;

I'll let you fill in the other class methods ...

Example of using:

procedure TForm1.AddMemoToTree(ANode: TTreeNode; AMemo: TMemo);
var
  Ms: TMemoSource;
begin
  Ms := MemoSources1.AddItem;
  Ms.Strings.Assign(AMemo.Lines);
  Ms.Node := TreeView1.Items.AddChildObject(ANode, 'Memo' + IntToStr(Ms.Id), Ms);
end;

I find the biggest advantage of maintaining a list is you can hunt the list by Id or Node rather than the treeview. The list approach also lends itself to dynamically adding and deleting nodes to the treeview in the OnExpanding and OnCollapsing events remembering to set Ms.Node := nil if you delete a treenode and don't delete the corresponding memosource.

Nincsenek megjegyzések:

Megjegyzés küldése