The TreeView control implements a data structure known as a tree. A tree is the most appropriate structure for storing hierarchical information. The organizational chart of a company, for example, is a tree structure. Every person reports to another person above him or her, all the way to the president or CEO. Figure 4.21 depicts a possible organization of continents, countries, and cities as a tree. Every city belongs to a country, and every country to a continent. In the same way, every computer file belongs to a folder that may belong to an even bigger folder, and so on up to the drive level. You can’t draw large tree structures on paper, but it’s possible to create a similar structure in the computer’s memory without size limitations.
Each item in the tree of Figure 4.21 is called a node, and nodes can be nested to any level. Oddly, the top node is the root of the tree, and the subordinate nodes are called child nodes. If you try to visualize this structure as a real tree, think of it as an upside-down tree with the branches emerging from the root. The end nodes, which don’t lead to any other nodes, are called leaf nodes or end nodes.
Figure 4.21 – The World View as Tree
To locate a city, you must start at the root node and select the continent to which the city belongs. Then you must find the country (in the selected continent) to which the city belongs. Finally, you can find the city you’re looking for. If it’s not under the appropriate country node, it doesn’t exist.
Note: The items displayed on a TreeView control are just strings. Moreover, the TreeView control doesn’t require that the items be unique. You can have identically named nodes in the same branch — as unlikely as this might be for a real application. There’s no property that makes a node unique in the tree structure or even in its own branch.
You can also start with a city and find its country. The country node is the city node’s parent node. Notice that there is only one route from child nodes to their parent nodes, which means that you can instantly locate the country or continent of a city. The data of Figure 4.21 is shown in Figure 4.22 in a TreeView control. Only the nodes we’re interested in are expanded. The plus sign indicates that the corresponding node contains child nodes. To view them, click the button with the plus sign to expand the node.
Figure 4.22 – The tree implemented with a TreeView control
The tree structure is ideal for data with parent-child relations (relations that can be described as belongs to or owns). The continents-countries-cities data is a typical example. The folder structure on a hard disk is another typical example. Any given folder is the child of another folder or the root folder.
Many programs are based on tree structures. Computerized board games use a tree structure to store all possible positions. Every time the computer has to make a move, it locates the board’s status on the tree and selects the ‘‘best’’ next move. For instance, in tic-tac-toe, the tree structure that represents the moves in the game has nine nodes on the first level, which correspond to all the possible positions for the first token on the board (the X or O mark). Under each possible initial position, there are eight nodes, which correspond to all the possible positions of the second token on the board (one of the nine positions is already taken). On the second level, there are 9 × 8, or 72, nodes. On the third level, there are 7 child nodes under each node that correspond to all the possible positions of the third token, a total of 72 × 7, or 504 nodes, and so on. In each node, you can store a value that indicates whether the corresponding move is good or bad. When the computer has to make a move, it traverses the tree to locate the current status of the board, and then it makes a good move.
Of course, tic-tac-toe is a simple game. In principle, you could design a chess game by using a tree. This tree, however, would grow so large so quickly that it couldn’t be stored in any reasonable amount of memory. Moreover, scanning the nodes of this enormous tree would be an extremely slow process. If you also consider that chess moves aren’t just good or bad (there are better and not-so-good moves), and you must look ahead many moves to decide which move is the best for the current status of the board, you’ll realize that this ad hoc approach is totally infeasible. Practically speaking, such a program requires either infinite resources or infinite time. That’s why the chess-playing algorithms use heuristic approaches, which store every recorded chess game in a database and consult this database to pick the best next move.
Maintaining a tree structure is a fundamental operation in software design; computer science students spend a good deal of their time implementing tree structures. Fortunately, with Visual Basic you don’t have to implement tree structures on your own. The TreeView control is a mechanism for storing hierarchically structured data in a control with a visible interface. The TreeView control hides (or encapsulates, in object-oriented terminology) the details of the implementation and allows you to set up tree structures with a few lines of code — in short, all the gain without the pain (almost).
The ListView control implements a simpler structure, known as a list. A list’s items aren’t structured in a hierarchy; they are all on the same level and can be traversed serially, one after the other. You can also think of the list as a multidimensional array, but the list offers more features. A list item can have subitems and can be sorted according to any column. For example, you can set up a list of customer names (the list’s items) and assign a number of subitems to each customer: a contact, an address, a phone number, and so on. Or you can set up a list of files with their attributes as subitems. Figure 4.23 shows a Windows folder mapped on a ListView control. Each file is an item, and its attributes are the subitems. As you already know, you can sort this list by filename, size, file type, and so on. All you have to do is click the header of the corresponding column.
Figure 4.23 – A folder’s files displayed in a ListView control (Details view)
The ListView control is a glorified ListBox control. If all you need is a control to store sorted objects, use a ListBox control. If you want more features, such as storing multiple items per row, sorting them in different ways, or locating them based on any subitem’s value, you must consider the ListView control. You can also look at the ListView control as a view-only grid.
The TreeView and ListView controls are commonly used along with the ImageList control. The ImageList control is a simple control for storing images so they can be retrieved quickly and used at runtime. You populate the ImageList control with the images you want to use on your interface, usually at design time, and then you recall them by an index value at runtime. Before we get into the details of the TreeView and ListView controls, a quick overview of the ImageList control is in order.