TAdvTreeView problem using GetFirstChild

I'm new to the TAdvTreeView component, but it does not work as I expect it to.
I have the following code. Why is ChildNode nil here?

procedure TForm1.Button1Click(Sender: TObject);
var
  TreeNode  : TAdvTreeViewNode;
  HoofdNode : TAdvTreeViewNode;
  ChildNode : TAdvTreeViewNode;
  nTeller   : Integer;
begin
  TV.BeginUpdate;
  Try
    TV.ClearNodes;
    HoofdNode              := TV.AddNode;
    HoofdNode.Text[0]      := 'Programma''s';
    HoofdNode.Extended     := True;
    TreeNode               := TV.AddNode(HoofdNode);
    TreeNode.Text[0]       := 'Programma1';
    TreeNode.CheckTypes[0] := tvntCheckBox;
    TreeNode.Checked[0]    := False;
    TreeNode.Text[1]       := '1';
    TreeNode.Text[2]       := '0';
    TreeNode               := TV.AddNode(HoofdNode);
    TreeNode.Text[0]       := 'Programma2';
    TreeNode.CheckTypes[0] := tvntCheckBox;
    TreeNode.Checked[0]    := False;
    TreeNode.Text[1]       := '2';
    TreeNode.Text[2]       := '0';
    ChildNode              := HoofdNode.GetFirstChild;
    if ChildNode <> nil then
    begin
      repeat
        for nTeller := 0 to 4 do
        begin
          TreeNode               := TV.AddNode(ChildNode);
          TreeNode.Text[0]       := 'Versie '+IntToStr(nTeller+1);
          TreeNode.CheckTypes[0] := tvntCheckBox;
          TreeNode.Checked[0]    := True;
          TreeNode.Text[1]       := '0';
          TreeNode.Text[2]       := IntToStr(nTeller);
        end;
        ChildNode := ChildNode.GetNextSibling;
      until ChildNode = nil;
    end;
  Finally
    TV.EndUpdate;
    TV.ExpandAll;
  End;
end;



When using BeginUpdate / EndUpdate you are speeding up the process of building the treeview, yet it implies that the internal node structure creation is bundled into an endupdate. You need to use the GetFirst outside of the BeginUpdate / EndUpdate, or remove the BeginUpdate / EndUpdate or access the Nodes collection directly.

I see. I mainly use the Beginupdate / Endupdate to prevent the user seeing the bulding of the tree.
I guess there is no other way to do that?

Unfortunately no, but if you are not loading many nodes performance shouldn't be to mich affected, you could use 2 BeginUpdate / EndUpdates blocks. One for adding the nodes and the second for manipulation of existing nodes. The nodestructure will be available in the second loop.

Ok, I'll try that. Thank you for the quick response.

In the same component I have a problem with the 'Checked' values.
I use code like below to cascade the 'Checked' values to lower nodes, but those events are never fired. Why?

// fill nodes

TVprogrammas.ClearNodes;
HoofdNode          := TVprogrammas.AddNode;
HoofdNode.Text[0]  := 'Programma''s';
HoofdNode.Extended := True;
programmas         := Data.ClientConnectie.Client.List<Tprogrammas>('$orderby=naam');
Try
  if programmas.Count>0 then
  begin
    for nProgrammaTeller:=0 to programmas.Count-1 do
    begin
      programmanode               := TVprogrammas.AddNode(HoofdNode);
      programmanode.Text[0]       := programmas[nProgrammaTeller].naam;
      programmanode.CheckTypes[0] := tvntCheckBox;
      programmanode.Checked[0]    := False;
      programmanode.Text[1]       := IntToStr(programmas[nProgrammaTeller].programmasid);
      programmanode.Text[2]       := '0';
    end;
  end;
Finally
  programmas.Free;
End;

// Check node

procedure TFormHoofd.TVlicentiesAfterCheckNode(Sender: TObject;
  ANode: TAdvTreeViewVirtualNode; AColumn: Integer);
var
  ChildNode: TAdvTreeViewNode;
begin
  ChildNode := ANode.Node.GetFirstChild;
  while ChildNode <> nil do
  begin
    Childnode.Checked[AColumn] := True;
    Childnode := ChildNode.GetNextSibling;
  end;
end;

// Uncheck node

procedure TFormHoofd.TVlicentiesAfterUnCheckNode(Sender: TObject;
  ANode: TAdvTreeViewVirtualNode; AColumn: Integer);
var
  ChildNode: TAdvTreeViewNode;
begin
  ChildNode := ANode.Node.GetFirstChild;
  while ChildNode <> nil do
  begin
    Childnode.Checked[AColumn] := False;
    Childnode := ChildNode.GetNextSibling;
  end;
end;


Hi, 


If you refer to the events never get called when programmatically checking a node then this is by design. Events are never triggered when programmatically changing a value, only with user interaction.

No, I don't mean programmatically.
I fill the nodes in a way decribed above. I forgot to mention that their is MUCH more code that fills different childs from the programmanodes in the same way.
I then check a node (by user-interaction) and the events don't get triggered.

Hi, sorry for the inconvenience Pieter, but I messed up. I have two TreeViews and I programmed the events in the other treeview.... So they don't get fired....

I do have two more questions though.
- Can I switch a complete branch of a tree on of off with one click (by cascading down all the children and their children etc).
- Can the state of the checkbox reflect that not all children are switched on or off? Normally one sees a little square in the box when not all are switched on.

Hi Pieter,

I managed to solve my first question with a piece of recursive code.
My second question still stands, though, hopefully you can answer that one:

- Can the state of the checkbox reflect that not all children are
switched on or off? Normally one sees a little square in the box when
not all are switched on.

You can collapse/expand all nodes with the following code:

type
  TAdvTreeViewProtected = class(TAdvTreeView);
...
implementation
...

procedure TForm1.AdvTreeView1BeforeCollapseNode(Sender: TObject;
  ANode: TAdvTreeViewVirtualNode; var ACanCollapse: Boolean);
begin
  ACanCollapse := False;
  TAdvTreeViewProtected(AdvTreeView1).BlockUpdateNode := False;
  ANode.Collapse(True);
  TAdvTreeViewProtected(AdvTreeView1).BlockUpdateNode := False;
end;

procedure TForm1.AdvTreeView1BeforeExpandNode(Sender: TObject;
  ANode: TAdvTreeViewVirtualNode; var ACanExpand: Boolean);
begin
  ACanExpand := False;
  TAdvTreeViewProtected(AdvTreeView1).BlockUpdateNode := False;
  ANode.Expand(True);
  TAdvTreeViewProtected(AdvTreeView1).BlockUpdateNode := False;
end;

The state of the checkbox can unfortunately not be set to mixed mode as this is not supported in FireMonkey. We will investigate if we can add support for this.

Pieter Scheldeman2016-06-10 11:59:50