Skip to main content
A newer version of this page is available. .

Using the Nodes Iterator

  • 6 minutes to read

Generally, nodes are organized in a tree-like structure. Basically, you will need to write recursive code to visit all the nodes in such instances. The Tree List introduces Nodes Iterator technology, which lets you avoid this, and makes traversing through the nodes a trivial task. This topic provides an overview of the Nodes Iterator, and several use examples.

 

Nodes Iterator Overview

The Nodes Iterator is an object which can be accessed via the Tree List’s TreeList.NodesIterator property. This object is capable of traversing through the nodes which have been arranged into a tree (it implements recursive code to do this). So, you don’t have to write any code for this purpose. The only thing you need to do is to process each node that is accessed. The following steps need to be performed:

  • Create an operation class - a descendant of the TreeListOperation class. The main thing to be done when creating the operation class is to override the TreeListOperation.Execute method, which is automatically called each time a node is visited. The visited node is then passed to this method as its parameter.
  • Call the TreeListNodesIterator.DoOperation or TreeListNodesIterator.DoLocalOperation method of the Nodes Iterator, and pass the operation object to it. These methods differ in the scope of nodes they process. The first scans through all the nodes within the control; the second, only the nodes of the sub-tree whose parent is specified by the parameter.

You can also pass lambda expressions as delegate parameters to the TreeListNodesIterator.DoOperation or TreeListNodesIterator.DoLocalOperation methods. This approach allows you to significantly simplify the code in some cases. Below is an example of using the Nodes Iterator to calculate the total number of nodes.


int count = 0;
treeList1.NodesIterator.DoOperation((n) => count++);

More capabilities provided by the Node Iterator are described later on in this topic.

Example

The following example shows how to use the Nodes Iterator to obtain the number of nodes which reside on the specified nesting level.

In the example, a CustomNodeOperation object is created that is used to calculate this number. The operation class contains an internal counter that is incremented by one each time a node that resides at the specified nesting level is accessed.

To get the total number of the nodes which reside at the specified nesting level, a CustomNodeOperation instance is created and passed to the TreeListNodesIterator.DoLocalOperation method. After the method has been performed, the CustomNodeOperation.NodeCount property is read to get the number of nodes.

using DevExpress.XtraTreeList.Nodes;
using DevExpress.XtraTreeList.Nodes.Operations;

// Declaring the custom operation class.
class CustomNodeOperation : TreeListOperation {
   int level;
   int nodeCount;
   public CustomNodeOperation(int level) : base() {
      this.level = level;
      this.nodeCount = 0;
   }
   public override void Execute(TreeListNode node) {
      if(node.Level == level)
         nodeCount++;
   }
   public int NodeCount {
      get { return nodeCount; }
   }
}

// ...

CustomNodeOperation operation = new CustomNodeOperation(2);
treeList1.NodesIterator.DoLocalOperation(operation, treeList1.Nodes);
int totalNodesAtSecondLevel = operation.NodeCount;

Extended Capabilities of the Nodes Iterator

When creating an operation class, you can also override other TreeListOperation properties and methods to implement additional functionality:

TreeListOperation Member

Description

The TreeListOperation.NeedsFullIteration property

If this property returns false, only nodes that have children are visited. Otherwise the Nodes Iterator visits all the nodes within the range. As implemented in the TreeListOperation class, this property returns true. So, it’s not necessary to override it if you want to traverse through the nodes regardless of whether they have children or not.

You can also manually check whether the processed node has children when overriding the TreeListOperation.Execute method. In this case, the operation will require much more time to complete since the iterator will still visit every node, and call the TreeListOperation.Execute method of each one. Overriding the TreeListOperation.NeedsFullIteration property however, will bring a performance benefit if you need to perform an operation which only processes the parent nodes (for instance, expanding and collapsing specific nodes).

The TreeListOperation.NeedsVisitChildren method

This method is called each time a node which contains child nodes is visited. This parent node is then passed to the TreeListOperation.NeedsVisitChildren method as a parameter which is then examined to return a Boolean value. The value returned depends upon the TreeListOperation.NeedsFullIteration property’s value. If this property is set to true, then this method will return a value which indicates whether it’s necessary to visit all the children of the specified node. Otherwise, the method returns a value which specifies whether the parent node should itself be processed, together with its child nodes.

Overriding the TreeListOperation.NeedsVisitChildren method will provide a performance benefit to your applications. For instance, you may want to process nodes which reside on the first two levels only. In this case, the TreeListOperation.NeedsVisitChildren method returns false for each parent node which resides on the second level, so that the lower level nodes are not processed.

The TreeListOperation.CanContinueIteration method.

This method is called before the operation which is implemented in the TreeListOperation.Execute method is performed on the processed node. As implemented in the TreeListOperation class, the TreeListOperation.CanContinueIteration method returns true. This means that the iteration is stopped after all nodes have been processed. If this method returns false, the iteration process is stopped. Overriding this method can be useful, for example, when implementing the node’s search.

The TreeListOperation.FinalizeOperation method.

This method can be overridden to perform final operations and free allocated resources.

Example

The following example shows how to create an operation class that will collapse all the nodes which do not contain the specified node as their child. Only the node’s parents will be expanded as a result.

The operation class accepts the node as its constructor parameter and stores it in an internal variable. The Execute method checks whether the processed node contains the specified node as a child. If not, the processed node is collapsed. The operation class also overrides the TreeListOperation.NeedsFullIteration property to process only the nodes that have children. This provides performance benefits when working with large and complex node structures.

The image below shows the Tree List before and after executing the sample code:

CD_UsingNodesIterator

using DevExpress.XtraTreeList.Nodes;
using DevExpress.XtraTreeList.Nodes.Operations;

public class CollapseExceptSpecifiedOperation : TreeListOperation {
   TreeListNode visibleNode;
   public CollapseExceptSpecifiedOperation(TreeListNode visibleNode) : base() {
      this.visibleNode = visibleNode;
   }
   public override void Execute(TreeListNode node) {
      if (!visibleNode.HasAsParent(node))
         node.Expanded = false;
   }
   public override bool NeedsFullIteration { get { return false; } }
}

//...

treeList1.NodesIterator.DoOperation(new CollapseExceptSpecifiedOperation(treeList1.FocusedNode));