Skip to main content

Dynamic Loading

  • 4 minutes to read

The ExpressQuantumTreeList control enables you to implement dynamic loading of its nodes, i.e. by only loading its root level nodes when the application starts. Child nodes are loaded as their parent nodes are expanded. This technique is applicable only to the unbound TcxTreeList control.

This topic provides a simple example of implementing dynamic loading. It reads the file structure of your local hard drive and displays it within the TreeList.

To use dynamic loading

  • Create the methods that will be used to load child nodes for the specified parent node. These methods can also be used to fill the root level with nodes. Note: the TreeListNode.HasChildren node property must be set to True for nodes that will contain child nodes. This displays the expanding/collapsing button for such nodes.

  • Fill the root level with nodes when the application starts.

  • Handle the TreeList.OnExpanding event. The handler must add child nodes to the node being expanded.

All these items will be implemented in the sample application below.

As was stated above, dynamic loading can only be implemented when working in unbound mode. Use the TcxTreeList control to work in unbound mode. Three columns are created in this example: Name, Type, and Size.

You can use the following code to create the columns required:

//...
var
  FColumn: TcxTreeListColumn;
begin
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Name';
  FColumn.PropertiesClass := TcxTextEditProperties;
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Type';
  FColumn.PropertiesClass := TcxTextEditProperties;
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Size';
  FColumn.PropertiesClass := TcxTextEditProperties;
//...

The next step is to declare a procedure to search for the files and folders at the specified path and to create the nodes required. The ScanPath procedure declared below performs this task. It receives the path of files to be displayed within the parent node and the parent node itself as its parameters. When calling this procedure to fill the root level (in the TForm.OnCreate event handler) the root path is specified as the first parameter and TreeList.Root is passed as the parent node. The TreeListNode.HasChildren property for each node displaying a folder is set to True. This forces the TreeList control to display expand buttons for these nodes.

procedure TForm1.ScanPath(APath: string; AParent: TcxTreeListNode);
var
  FHandle: Integer;
  FSearchRec: TSearchRec;
  FNode: TcxTreeListNode;
  function AddFileNode(AName: string; ASize: string): TcxTreeListNode;
  var
    FNode: TcxTreeListNode;
  begin
    FNode := AParent.AddChild;
    with FNode do
    begin
      Texts[0] := AName;
      Texts[2] := ASize;
    end;
    Result := FNode;
  end;
begin
  FHandle := FindFirst(APath + '\*.*', faAnyFile, FSearchRec);
  if FHandle = 0 then
  repeat
    if (FSearchRec.Name <> '.') and (FSearchRec.Name <> '..') then
    begin
      if (FSearchRec.Attr and faDirectory) <> 0 then
      begin
        FNode := AddFileNode(APath + FSearchRec.Name + '\', ' ');
        FNode.Texts[1] := 'Folder';
        FNode.HasChildren := True;
      end else
      begin
        FNode := AddFileNode(FSearchRec.Name, IntToStr(FSearchRec.Size));
        FNode.Texts[1] := 'File';
      end
    end;
   until FindNext(FSearchRec) <> 0;
  FindClose(FSearchRec);
end;

After declaring this procedure, you can write code to fill the root level with nodes. The following code can be used for this purpose (it sets the “C:" logical drive to be the root):

procedure TForm1.FormCreate(Sender: TObject);
var
  FColumn: TcxTreeListColumn;
begin
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Name';
  FColumn.PropertiesClass := TcxTextEditProperties;
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Type';
  FColumn.PropertiesClass := TcxTextEditProperties;
  FColumn := cxTreeList1.CreateColumn;
  FColumn.Caption.Text := 'Size';
  FColumn.PropertiesClass := TcxTextEditProperties;
  ScanPath('C:\', cxTreeList1.Nodes.Root);
end;

The last step is to implement dynamic loading. When an end-user expands a folder node, the TreeList control’s OnExpanding event fires. Call the ScanPath procedure in the event’s handler and pass the first column value of the expanded node and node as procedure parameters. Check the node’s Count property value to avoid duplicating child nodes on expanding their parent node.

procedure TForm1.cxTreeList1Expanding(Sender: TObject;
  ANode: TcxTreeListNode; var Allow: Boolean);
begin
  if ANode.Count = 0 then
    ScanPath(ANode.Texts[0], ANode);
end;

Now you can run the application. Child nodes will be loaded when nodes are expanded.