Understanding Infragistic controls: Tree View
There are so many questions on different forums about how to work with
Infragistics controls that I decided to share my experience working with
them in TestComplete. This article explains how to create two
functions. The first function gets the selected item in a tree view,
and the second function demonstrates how to select an item in the tree.
This is the first of several articles which will describe how to work
with different Infragistics controls in TestComplete. I hope they will
be useful for you.
There are two actions you usually need to do with tree view controls: Selecting an item and getting the currently selected item. I'll describe step-by-step how to create both of these functions.
The following TestComplete options were set while creating these samples:
Object Tree Model: Flat
Getting selected items
I'll start with creating a function that will allow you to get the currently selected item because it's easier than the selecting function.
First, we'll use the TestComplete Object Browser to find the full name of the selected property.
Run the application to be tested that's uses an Infragistics Tree View control. Navigate in the tested application to a window with the Tree View control.
In the TestComplete Object Browser, locate the icon representing your tested app and open it, then open the sub nodes and locate the Tree View control.
Select the Infragistics TreeView control in the TestComplete Object Browser and double click on it's SelectedNodes property. This property contains all information about currently selected items.
Now let's suppose that only one item can be selected at any moment. In this case we need to double click on the Params button in the Object Browser near the Item property and enter 0 for the Param1 parameter. Zero is the index of the first item in SelectedNodes property.
And then double click on the Item property in the Object Browser. Now you are seeing properties of the exact selected item. Look for the FullPath property. This is what you need: the full name of the selected property.
Here is a very simple function which returns full name of the currently selected item of an Infragistic TreeView:
However it will work only if there is at least one node selected. If not, an exception will be generated: "Index was out of range. Must be non-negative and less than the size of the collection." It happens because property SelectedNodes.Item is empty. To avoid this exception we need to check whether at least one item selected. To do this we can use property SelectedNodes.Count. Now our function will look as shown below:
And the last step we need to do is to write another function, which will return all selected items if several of them selected:
Also you can use tree view method get_SelectedNodes() instead of Nodes property. In this case code for getting an item will be like this:
Selecting an item
That was easy enough, now we need to create a function which will select an item.
All nodes in the Infragistics Tree View are represented by a Nodes property. This is a compound property which can contain other Nodes. Each Nodes property also has Count property which contains number of its child nodes and Item property for working with each child node.
Before we start to create our function we need to understand its logic. The function will get the full path to the item (it will be the same full path we've got from ITreeGetSelectedItem) and then it will select and expand all items from the highest node to the lowest one. If some item is not found, the function should exit and return false.
Here is the simplest code example of how to select a node in a tree view. The function has two parameters: a tree view object and an item to be selected. The symbol "|" is used as separator between nodes.
This example will work in most cases. However there may be a problem using the set_Selected() method. Some Infragistics tree views allow you to select several nodes at the same time. But only one item can be active at one time. Also, if an item is selected it doesn't means it is active, and if an item is active it can be not selected. When a user selects an item using the mouse it becomes selected and active at once. If user holds Ctrl and selects several items only the last one will be active.
Thus if the application works with the ActiveNode property of the tree view it will work incorrectly after using the set_Selected() method because the ActiveNode won't be changed. To solve this problem we should do a mouse click on the tree view item instead of using set_Selected().
So we need to modify our function. We will replace set_Selected() with a mouse click. To do this we should get coordinates of the item. Here is the code which we must write instead of oNode.set_Selected(true):
iX = oNode.Bounds.Right - (oNode.Bounds.Right - oNode.Bounds.Left) / 2;
iY = oNode.Bounds.Bottom - (oNode.Bounds.Bottom - oNode.Bounds.Top) / 2;
iX, iY are coordinates of the center of the item.
And finally we have one more problem. If there will be many items in the tree view and after expanding the item to be clicked will be out of tree view window bounds. TestComplete will generate an error "There was an attempt to perform a click at point (..., ...) which is out of the window bounds."
We should scroll the tree view before clicking an item to avoid this error. Node method IsInView() can be used to check whether node is visible and tree view method ScrollNodeIntoView() can be used to scroll a tree view before clicking:
Note, that there is also a method BringIntoView() defined for Nodes and you can use it instead of ScrollNodeIntoView():
And here is the final version of the ITreeSelectItem() function and it's usage example. I've added a few Log functions and I would recommend to do this for all your common functions, because it will be easier to find an error if the function fails.
Also, comparing items has been changed from checking equality to matching. It is useful in case when you don't know te exact text of the node (e.g. the node text contains a number of subitems which may differ from time to time).
if (oNode.Nodes.Item(j).Text.OleValue == aNodes[i])
has been replaced with this code: