TAdvTreeView - Traversing within Begin/End update

Hi Pieter,

Is it possible to traverse the tree using something like:

  Node:=GetFirstRootNode;
  while Node<>NIL do
  begin
     //do something
     Node:=Node.GetNext;
  end;

while within a BeginUpdate / EndUpdate phase.

I have a number of tree population routines that rely on me searching the existing tree structure to find each new node's parent (basically, I'm displaying a flat data structure in tree form)

In a standard treeview I can use code similar to the above to search for the parent nodes as I add each new node, but it doesnt work for an AdvTreeView (if I'm within a BeginUpdate/EndUpdate phase)

Obviously, I can populate without using BeginUpdate/EndUpdate but was worried that would slow things down too much.

Is there a recommended way of traversing the grid within a Begin/EndUpdate. I'm using collection based nodes, by the way.

Regards
Steve Collins

Hi Steve, 


BeginUpdate and EndUpdate block the creation of the internal node structure. When using GetFirstRootNode or GetNext the internal node structure is addressed, therefore returning nil between a BeginUpdate and EndUpdate in combination with adding nodes. The blocking call makes sure no calculation, or internal structures are made, that slow down the creation of the TreeView, but this depends ofcourse of the number of total nodes and subnodes that will be added. 

Accessing the root node from a specific node within a BeginUpdate / EndUpdate block can be done by using the collection property, as demonstrated in the sample below.

var
  t: TAdvTreeView;
  n, pn, rn: TAdvTreeViewNode;
begin
  t.BeginUpdate(True);
  n := t.Nodes.Add;
  n.Text[0] := 'ROOT';
  n := n.Nodes.Add;
  n.Text[0] := 'SUB1';
  n := n.Nodes.Add;
  n.Text[0] := 'SUB2';
  n := n.Nodes.Add;
  n.Text[0] := 'SUB3';

  rn := nil;
  pn := (n.Collection as TAdvTreeViewNodes).Node;
  while Assigned(pn) do
  begin
    rn := pn;
    pn := (pn.Collection as TAdvTreeViewNodes).Node;
  end;

  if Assigned(rn) then
  begin
    rn.Text[0]; //-> 'ROOT'
  end;

  t.EndUpdate;
end;

The same applies to the designtime initialized cars treeview:

var
  t: TAdvTreeView;
  n, rn, pn: TAdvTreeViewNode;
begin
  t := TAdvTreeView.Create(Self);
  t.BeginUpdate(True);
  t.InitSample;

  n := t.Nodes[0].Nodes[1].Nodes[1];

  rn := nil;
  pn := (n.Collection as TAdvTreeViewNodes).Node;
  while Assigned(pn) do
  begin
    rn := pn;
    pn := (pn.Collection as TAdvTreeViewNodes).Node;
  end;

  if Assigned(rn) then
  begin
    rn.Text[0]; //-> 'Audi'
  end;

  t.EndUpdate;

You could bundle the while loop into a separate function with the TAdvTreeViewNode as a parameter, and return the variable rn as the root node for that specific node.

Kind Regards, 
Pieter

Pieter Scheldeman2016-02-12 22:14:28