Delphi – Updating Treeview Node Images correctly

delphitreeview

I am using a TTreeView with a TImageList. My Treeview is represented similar to a Windows Treeview where I have Group nodes and Item nodes.

When the Group nodes are created, they have 2 imageindexes as set in the Imagelist, one is for the closed folder (imgGroupClosed) icon the second is for the open folder (imgGroupOpen) icon.

When I add other types of node, they use a different icon also set from the Imagelist.

Now onto my question, how do I make sure the Group nodes show the correct icon? for example if I delete or move a child item node, the group that no longer has any children should show as closed but it shows as open.

I tried writing a reusable procedure like so:

procedure TfrmMain.UpdateGroupImages;
var
  Node: TTreeNode;
  i: Integer;
begin
  if TreeView1.Items.Count > 0 then
  begin
    for i := 0 to TreeView1.Items.Count - 1 do
    begin
      Node := TreeView1.Items[i];

      case Node.ImageIndex of
        imgGroupClosed, imgGroupOpen:
          begin
            if Node.HasChildren then
            begin
              if Node.Expanded then
              begin
                Node.ImageIndex := imgGroupOpen;
                Node.SelectedIndex := imgGroupOpen;
              end
              else
              begin
                Node.ImageIndex := imgGroupClosed;
                Node.SelectedIndex := imgGroupClosed;
              end
            end
            else
            begin
              Node.ImageIndex := imgGroupClosed;
              Node.SelectedIndex := imgGroupClosed;
            end;
          end;
      end;
    end;
  end;
end;

I have been calling this in some of the Treeview events such as OnCollapsed, OnExpanded, OnDeletion, OnDragDrop etc but it doesnt seem to be working correctly.

Is there a better way of doing this, or could someone help update/fix my code above?

Basically the problem I am getting is the group nodes dont update the images correctly, so sometimes I am left with a open folder icon when there is no children or not expanded etc.

Thanks, Craig.

Best Answer

Add BeginUpdate and EndUpdate as follows and it should work:

procedure TfrmMain.UpdateGroupImages;
var
  Node: TTreeNode;
  i: Integer;
begin
  TreeView1.BeginUpdate;
  try
    if TreeView1.Items.Count > 0 then
    begin
      for i := 0 to TreeView1.Items.Count - 1 do
      begin
        Node := TreeView1.Items[i];

        case Node.ImageIndex of
          imgGroupClosed, imgGroupOpen:
            begin
              if Node.HasChildren then
              begin
                if Node.Expanded then
                begin
                  Node.ImageIndex := imgGroupOpen;
                  Node.SelectedIndex := imgGroupOpen;
                end
                else
                begin
                  Node.ImageIndex := imgGroupClosed;
                  Node.SelectedIndex := imgGroupClosed;
                end
              end
              else
              begin
                Node.ImageIndex := imgGroupClosed;
                Node.SelectedIndex := imgGroupClosed;
              end;
            end;
        end;
      end;
    end;
  finally
    TreeView1.EndUpdate;
  end;
end;
Related Topic