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

Using the Rows Iterator

  • 8 minutes to read

Rows in the vertical grids (VGridControl and PropertyGridControl) can be organized in a tree-like structure. Basically, you will need to write recursive code to visit all rows is such a case. However, the Rows Iterator technology introduced by the vertical grids enables you to avoid this and make traversing through rows a trivial task. This topic provides an overview of the Rows Iterator and several examples of using it.

Rows Iterator Overview

Rows Iterator is an object which can be accessed via the VGridControlBase.RowsIterator grid property. This object is capable of traversing through rows arranged into a tree (it implements recursive code for this purpose). So, you do not have to write any code to traverse through the grid’s rows. The only thing you need to do is to process each row accessed. The following steps need to be performed:

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

Actually, the row iterator provides more capabilities than are described in the list above, they are described later on in this topic. Before reading that information review the following two simple examples for using the rows iterator.

Row Counter Sample

This example will use the rows iterator to get the total number of rows within the grid. The operation class will have an internal counter for this purpose which is incremented by one each time a row is accessed. There will also be a public property which allows access to the counter value after row traversal has finished. So the code for the operation class is:


public class CountOperation : RowOperation {
   int totalRows;
   public CountOperation() : base() {
      totalRows = 0;
   }
   public override void Execute(BaseRow row) {
      totalRows++;
   }
   public int TotalRows { get { return totalRows; } }
}

To get the total number of rows within the grid you need to create a new CountOperation object and pass it to the VGridRowsIterator.DoOperation method of the rows iterator and then read its TotalRows property value. The code below shows how this can be done.


CountOperation operation = new CountOperation();
vGridControl1.RowsIterator.DoOperation(operation);
int totalRows = operation.TotalRows;

Extended Capabilities of The Rows Iterator

When creating an operation class, you can override not only the RowOperation.Execute method. The RowOperation class provides two more virtual members that can be used to specify which rows need to be accessed. The list below enumerates these methods and explains their purpose.

  • The RowOperation.NeedsFullIteration property. If this property returns false only rows that have children are visited. Otherwise the rows iterator visits all rows within the range. As implemented in the RowOperation class, this property returns true. So it is not necessary to override it if you want to traverse through rows regardless of whether they have children or not.

    Of course, you can manually check whether the processed row has children in it RowOperation.Execute method implementation. However, in this case the operation will require much more time to complete, since the iterator will still visit every row and call the RowOperation.Execute method for them. Overriding the RowOperation.NeedsFullIteration property however will bring a performance benefit if you need to perform an operation which only processes parent rows (for instance, expanding and collapsing specific rows).

  • The RowOperation.NeedsVisitChildren method, this method is called each time a row containing child rows is visited. This parent row is then passed to the RowOperation.NeedsVisitChildren method as the parameter which is then examined to return a Boolean value. The value returned depends on the RowOperation.NeedsFullIteration property value, if the RowOperation.NeedsFullIteration property value is true then the method will return a value indicating it is necessary to visit all the children of the specified row. Otherwise, the method returns a value specifying whether to process the parent row itself together with its child rows.

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

The next two examples demonstrate how to use the RowOperation.NeedsFullIteration property and the RowOperation.NeedsVisitChildren method when constructing operation classes.

Obtain Rows Sample

This sample demonstrates how to obtain a collection of rows residing at a specific level. For this purpose the operation class declares a local variable which stores the level index, this variable is initialized in the constructor. If a row belonging to the specified level is found, it is added to the internal rows collection. The operation class also declares a public property which allows access to the collection of obtained rows.

The operation class introduced in the sample overrides the RowOperation.NeedsVisitChildren method for its base class. This is used to prevent rows whose nesting level is greater than that specified from being accessed. This increases application performance.


public class GetRowsAtLevelOperation : RowOperation {
   int level;
   ArrayList rows;
   public GetRowsAtLevelOperation(int level) : base() {
      this.level = level;
      rows = new ArrayList();
   }
   public override void Execute(BaseRow row) {
      if (row.Level == level)
         rows.Add(row);
   }
   public override bool NeedsVisitChildren(BaseRow row) {
      if (row.Level == level) 
         return false;
      return true;
   }
   public ArrayList Rows { get { return rows; } }
}

After such an operation has been declared, you can use the following code to restrict the resizing of all rows residing at the second nesting level.


GetRowsAtLevelOperation operation = new GetRowsAtLevelOperation(1);
vGridControl1.RowsIterator.DoOperation(operation);
foreach (object rowObject in operation.Rows) {
   BaseRow row = rowObject as BaseRow;
   row.Options &= ~VGridOptionsRow.AllowSize;
}

Collapse Rows Sample

This example shows how to create an operation class that will collapse all rows which do not contain the specified row as their child, So only the row’s parents will be expanded as a result.

The operation class accepts the row as its constructor parameter and stores it in an internal variable. The Execute method then checks whether the processed row contains the specified row as a child, if not, the processed row is collapsed. The operation class also overrides the RowOperation.NeedsFullIteration base class property to process only rows that have children. This gives a performance benefit when working with large row structures.

So, the code for this operation class is:


public class CollapseExceptSpecifiedOperation : RowOperation {
   BaseRow visibleRow;
   public CollapseExceptSpecifiedOperation(BaseRow visibleRow) : base() {
      this.visibleRow = visibleRow;
   }
   public override void Execute(BaseRow row) {
      if (!row.HasAsChild(visibleRow))
         row.Expanded = false;
   }
   public override bool NeedsFullIteration { get { return false; } }
}

If such an operation is declared you could for instance, collapse all the rows that do not contain the focused row as a child. The following code line should be used for this purpose.


vGridControl1.RowsIterator.DoOperation(new CollapseExceptSpecifiedOperation(vGridControl1.FocusedRow));