Правильная ссылка на эту страницу

Mapping of a tree with additional structure Data

Arkhangelskiy Andrey


       If we would like to show pictures in nodes of a tree and there is no possibility to use unrestricted variables ImageIndex, etc. it is possible to anchor to each node separate сруктуру Data and to fill it at construction of a tree. Thus in structure Data it is possible to write a table line completely. As it to make it is shown in an example {Example02}.
       For the beginning it is necessary to declare new type, for example, PItemRec specifying on record of type ITemRec which describes stored data. At least the record structure repeats a table design, but variants are possible. Declare new type as shown below:

type {Example02}
  PItemRec = ^ItemRec;
  ItemRec = record
  PId: integer;
  Parent: integer;
  PSurName: String;
  PBrDate: TDate;
  PStatus: String;
  PSalary: Double;

       PCount fields and POrder are not included in record ItemRec as are auxiliary and in the application do not vary.
       After that it is possible to change procedures from an example {Example01} as follows:

procedure TForm1.PeopleDatasetOpen(); {Example02}
   sFld,sCod  : String;
   ChildNode,NewNode : TTreeNode;
   RecNode : PItemRec;
   Cnt : Integer;
  If qrTVPeople.Database.Connected then begin
01   tvPeople.Items.Clear;
02   tvPeople.Items.BeginUpdate;
03   trTVPeople.Active := True;
04   qrTVPeople.Close;   qrTVPeople.SQL.Clear;
05   qrTVPeople.SQL.Add('Select * from People');
06   qrTVPeople.SQL.Add(' where Parent=0 and PID<>0');
07   qrTVPeople.SQL.Add(' order by POrder');
08   qrTVPeople.Open;     qrTVPeople.First;
09   While not qrTVPeople.EOF do begin
10      sCod := '';
11      If not VarIsNull(qrTVPeople.FieldValues['PStatus']) then begin
12         sCod := qrTVPeople.FieldValues['PStatus'];
13         sCod := sCod + ' - ';
14         end;
15      sFld := qrTVPeople.FieldValues['PSurName'];
16      New(RecNode);
17      RecNode^.PId    := qrTVPeople.FieldValues['PID'];
18      RecNode^.Parent := qrTVPeople.FieldValues['Parent'];
19                  Cnt := qrTVPeople.FieldValues['PCount'];
20      If not VarIsNull(qrTVPeople.FieldValues['PSurName'])
21             then RecNode^.PSurName:=qrTVPeople.FieldValues['PSurName'];
22      If not VarIsNull(qrTVPeople.FieldValues['PBrDate'])
23             then RecNode^.PBrDate:=qrTVPeople.FieldValues['PBrDate'];
24      If not VarIsNull(qrTVPeople.FieldValues['PStatus'])
25             then RecNode^.PStatus:=qrTVPeople.FieldValues['PStatus'];
26      If not VarIsNull(qrTVPeople.FieldValues['PSalary'])
27             then RecNode^.PSalary:=qrTVPeople.FieldValues['PSalary'];
28      NewNode:=tvPeople.Items.AddObject(tvPeople.TopItem,sCod+sFld,RecNode);
29      If Cnt>0 then 
30         ChildNode:=tvPeople.Items.AddChild(NewNode,IntToStr(Cnt));
31      NewNode.ImageIndex := 0; //Поставить картинку
32      qrTVPeople.Next;
33   end; // While not qrTVPeople.EOF do
34   tvPeople.Items.EndUpdate;
35   tvPeople.Update;
36   qrTVPeople.Close;      trTVPeople.Active := False;
   end; // qrTVPeople.Database.Connected

       Strings 01-15 have not varied, and here in string 16 we create a new record instance and in strings 17-27 we fill units of record with values from the table.
       In string 28 we create not simply a node, and a node with the object. Accordingly, there was an additional parameter in which we write the pointer to created record RecNode.
       In string 31 it is possible to assign number of a picture which will be shown about a node. Here it is possible to specify also number of a picture for ImageStatus.
       The second procedure which is called at disclosure of a node, also has undergone changes.
       In precisely the same way there is a new record instance, is filled with data and the pointer is transferred to it as parameter at creation of a node.

procedure TForm1.tvPeopleExpanding(Sender: TObject; Node: TTreeNode;
                                   var AllowExpansion: Boolean); {Example02}
   sFld,sCod : String;
   ChildNode,NewNode : TTreeNode;
   RecNode, RecChild : PItemRec;
   Cnt : Integer;
  If Node.HasChildren then begin
01   Node.DeleteChildren;  New(RecNode); RecNode := Node.Data;
02   trTVPeople.Active := True;
03   qrTVPeople.Close;  qrTVPeople.SQL.Clear;
04   qrTVPeople.SQL.Add('Select * from People');
05   qrTVPeople.SQL.Add(' where Parent='+IntToStr(RecNode.PId));
06   qrTVPeople.SQL.Add(' order by POrder');
07   qrTVPeople.Open;  qrTVPeople.First;
08   tvPeople.Items.BeginUpdate;
09   While not qrTVPeople.EOF do Begin
10      sCod := '';
11      If not VarIsNull(qrTVPeople.FieldValues['PStatus']) then begin
12         sCod := qrTVPeople.FieldValues['PStatus'] + ' - ';
13         end;
14      sFld := qrTVPeople.FieldValues['PSurName'];
15      New(RecChild);
16      RecChild^.PId    := qrTVPeople.FieldValues['PID'];
17      RecChild^.Parent := qrTVPeople.FieldValues['Parent'];
18                   Cnt := qrTVPeople.FieldValues['PCount'];
19      If not VarIsNull(qrTVPeople.FieldValues['PSurName'])
20             then RecChild^.PSurName:=qrTVPeople.FieldValues['PSurName'];
21      If not VarIsNull(qrTVPeople.FieldValues['PBrDate'])
22             then RecChild^.PBrDate:=qrTVPeople.FieldValues['PBrDate'];
23      If not VarIsNull(qrTVPeople.FieldValues['PStatus'])
24             then RecChild^.PStatus:=qrTVPeople.FieldValues['PStatus'];
25      If not VarIsNull(qrTVPeople.FieldValues['PSalary'])
26             then RecChild^.PSalary:=qrTVPeople.FieldValues['PSalary'];
27      newNode := tvPeople.Items.AddChildObject(Node,sCod+sFld,RecChild);
28      If Cnt>0 then 
29         ChildNode := tvPeople.Items.AddChild(NewNode,IntToStr(Cnt));
30      NewNode.ImageIndex := 0; //Поставить картинку
31      qrTVPeople.Next;
32   end; // While not qrTVPeople.EOF do
33      tvPeople.Items.EndUpdate;
34      trTVPeople.Active := False;
  end; // Node.HasChildren


       In string 01 it is deleted existing descendants, we create a new record instance and it is copied in it contents of record from a node.
       In strings 03-07 we build and we open inquiry for mapping descendants of a current node for what from the received record it is extracted PID a current node (string 05).
       Other strings repeat appropriate strings from PeopleDatasetOpen, except for string 27 where the node forms as derived to a current node, instead of to the radical of a tree.
       However, Delphi does not watch a memory allocation for additional data structures in nodes. Correctly to release memory at deleting a node it is necessary onDeletion to write a following code for event:

procedure TForm1.tvPeopleDeletion (Sender:TObject; Node:TTreeNode); {Example02}

© 01.07.2007, Arkhangelskiy A.G.

<<Prev. Table of contents
The beginning of section

Дата последнего изменения:
Thursday, 21-Aug-2014 09:10:44 MSK

Постоянный адрес статьи: