Home

Windows Controls: The Tree View

   

Introduction to the Tree View

 

Description

A tree view consists of displaying a hierarchical view of items arranged in a parent-child layout. It is typically used to show items that belong to interrelated categories, such as parent to child and child to grandchild, etc; or folder to subfolder to file.

The starting item of the tree is called the root and illustrates the beginning of the tree. Each item, including the root, that belongs to the tree is referred to as a node.

In the following charts, the down arrow means, "has the following child or children"

A tree view is not limited to a one-to-one correspondence. Not only can an item have more than one dependency, but also a child can make the tree stop at any category. Categories of a tree view are organized by levels. The most used trees have one parent called the root; then under the root start the dependents.

Here is an example representing the world and some countries:

The children of a parent are recognized by their belonging to the same level but can have different behaviors. For example, while one child may have another child (or other children), an item on the same level does not necessarily abide by a set rule. Everything usually depends on the tree designer.

Consider the following tree:

 

A member of a tree view is called a node. Visually, a node on a tree view displays its text in one of two states: selected or not selected. On another visual front, a node has a child or it is standing alone. When a node has a child, it displays a + (collapsed) or – (expanded) buttons. These last two details will be important because at times you will need to know whether a node is selected or not, whether a node has a child or not.

Practical LearningPractical Learning: Introducing the Tree View

  1. Start Embarcadero RAD Studio
  2. To create a new application, on the main meneu, click File -> New -> VCL Forms Application - C++Builder
  3. In the Object Inspector, change the characteristics of the form as follows:
    Caption: College Park Auto Parts - Part Selection
    Name: frmCentral
    Position: poScreenCenter
  4. In the Standard section of the Tool Palette, click the TPanel TPanel and click the form
  5. Using the Object Inspector, set its Align value to alTop
  6. In the Win32 section of the Tool Palette, click the TStatusBar and click an unoccupied area of the form
  7. In the Standard section of the Tool Palette, click the TPanel TPanel and an unoccupied area of click the form
  8. In the Object Inspector, click Align and select alLeft
  9. In the Additional section of the Tool Palette, click the TSplitter control TSplitter and click an unoccupied area of the form. Make sure it gets the alLeft value for the Align property
  10. In the Standard section of the Tool Palette, click TPanel TPanel and click an unoccupied area of the form
  11. In the Object Inspector, click Align and select alClient
  12. Execute the application to test it
  13. Close the form and return to your programming environment

Creating a Tree View

The tree view control is implemented in the Visual Component Library (VCL) by the TTreeView class that is defined in the ComCtrls.hpp library. The TTreeView class implements the TCustomTreeView class that is derived from TWinControl:

TTreeView Inheritance

To visually create a tree view, you can use the TTreeView control from the Win32 section of the Tool Palette. To programmatically create a tree view, you can declare a pointer to TTreeView and initialize it by specifying its parent. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Adding a Tree View

  1. Complete the design of the form as follows:
     
    College Park Auto Parts - Form Design
    Control Anchor Caption Name Other Properties
    TLabel Label   _______________    
    TLabel Label   College Park Auto Parts   Font: Tiffany Lt BT
    Font Size: 24
    Font Color: Blue
    TLabel Label   _______________    
    TLabel Label   Part Identification____    
    TLabel Label   Available Parts____    
    TTreeView TreeView [akLeft,akTop,akRight,akBottom]   tvwCarIdentification  
    TListView ListView [akLeft,akTop,akRight,akBottom]   lvwAvailableParts GridLines: True
    RowSelect: True
    ViewStyle: vsReport
    Columns    
    Alignment Caption Width
      Part # 75
      Part Name/Description 275
    taRightJustify Unit Price 75
  2. Execute the application to test it
  3. Close the form and return to your programming environment

Operations on Tree View's Nodes

 

Introduction to Creating Nodes

You can use TreeView Items Editor to create the nodes of a tree view at design time and in the TreeNode Editor. The branches of a tree view are stored in a property called Items. The Items property is an object based on the TTreeNodes class. As its name indicates, the Nodes property carries all of the branches of a tree view. This means that the Nodes property in fact represents a collection. Each member of this collection is called a node and it is an object based on the TTreeNode class.

At run time, to create a new node, call the TreeNodes::Add() method. Its syntax is:

TTreeNode* __fastcall Add(TTreeNode* Node, const AnsiString S);

If you are creating the first item of the tree view, the first argument must be passed as NULL. The second is the string that the branch will display. This means that this method is also the prime candidate to create the root node. Here is an example of calling it:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;

    tvwCountries->Left   = 12;
    tvwCountries->Top    = 12;
    tvwCountries->Width  = 220;
    tvwCountries->Height = 80;

    tvwCountries->Items->Add(NULL, "World");
}
//---------------------------------------------------------------------------

Countries Statistics

In the same way, you can call the TTreeNodes::Add() method as many times as necessary to create additional branches. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;

    tvwCountries->Left   = 12;
    tvwCountries->Top    = 12;
    tvwCountries->Width  = 220;
    tvwCountries->Height = 80;

    tvwCountries->Items->Add(NULL, "World");
    tvwCountries->Items->Add(NULL, "Jupiter");
    tvwCountries->Items->Add(NULL, "Neptune");
    tvwCountries->Items->Add(NULL, "Uranus");
}
//---------------------------------------------------------------------------

Countries Statistics

Practical LearningPractical Learning: Creating a Node

  1. In the Structure window, click frmCentral
  2. In the Object Inspector, click Events
  3. Double-click the right side of OnCreate
  4. To create the first node of the tree, implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCentral::FormCreate(TObject *Sender)
    {
        TTreeNode * nodRoot = tvwCarIdentification->Items->Add(NULL,
         				L"College Park Auto-Parts");
    }
    //---------------------------------------------------------------------------
  5. Press F9 to execute the application to test the form
  6. Close the form and return to your programming environment
  7. On the main menu, click File -> New -> Unit - C++Builder
  8. Change the header file as follows:
    //---------------------------------------------------------------------------
    
    #ifndef PartDescriptionH
    #define PartDescriptionH
    #include <vcl.h>
    //---------------------------------------------------------------------------
    class TPartDescription
    {
    public:
    	__fastcall TPartDescription(long code = 0,
    				    int year = 1960,
    				    UnicodeString mk = L"",
    				    UnicodeString mdl = L"",
    				    UnicodeString type = L"Unknown",
    				    UnicodeString desc = L"Unknown",
    				    double UPrice = 0.00);
    
    	long          PartNumber;
    	int           CarYear;
    	UnicodeString Make;
    	UnicodeString Model;
    	UnicodeString Category;
    	UnicodeString PartName;
    	double 	      UnitPrice;
    
    	__fastcall ~TPartDescription();
    };
    //---------------------------------------------------------------------------
    #endif
  9. access the source file and change it as follows:
    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    
    #include "PartDescription.h"
    
    //---------------------------------------------------------------------------
    
    #pragma package(smart_init)
    
    //---------------------------------------------------------------------------
    __fastcall TPartDescription::TPartDescription(long code,
    					      int year,
    					      UnicodeString mk,
    					      UnicodeString mdl,
    					      UnicodeString type,
    					      UnicodeString desc,
    					      double UPrice)
    {
    	PartNumber = code;
    	CarYear    = year;
    	Make       = mk;
    	Model      = mdl;
    	Category   = type;
    	PartName   = desc;
    	UnitPrice  = UPrice;
    }
    //---------------------------------------------------------------------------
    __fastcall TPartDescription::~TPartDescription()
    {
    }
    //---------------------------------------------------------------------------
  10. Display the main form
  11. On the main menu, click File -> Use Unit...
  12. In the list, click the only entry
  13. Make sure the Header radio button is selected and click OK

Creating Child Nodes

At design time and in the TreeView Items Editor, to create a child node for an existing item, first select it in the Items list, then click the New SubItem button. This causes a child node to be created for the selected item. To edit its name, first click it and change the string in the Text text box in the Item Properties section.

At run time, to create a child node, first get a reference to the node that will be used as its parent. One way you can get this reference is to obtain the returned value of the TreeNodes::Add() method. As its syntax indicates, this method returns a TreeNode object. Once you have this reference, to create a child node, you can call the TreeNodes::AddChild() method. Its syntax is:

TTreeNode* __fastcall AddChild(TTreeNode* Node, const AnsiString S);

To create a child node, you can pass the parent as the Node argument. The second argument is the text the new item will display. Here are examples:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TTreeView* tvwCountries = new TTreeView(this);
	tvwCountries->Parent = this;

	tvwCountries->Left   = 12;
	tvwCountries->Top    = 12;
	tvwCountries->Width  = 220;
	tvwCountries->Height = 90;

	TTreeNode * nodRoot = tvwCountries->Items->Add(NULL, "World");
	tvwCountries->Items->AddChild(nodRoot, "Africa");
	tvwCountries->Items->AddChild(nodRoot, "America");
	tvwCountries->Items->AddChild(nodRoot, "Asia");
	tvwCountries->Items->AddChild(nodRoot, "Europe");
}
//---------------------------------------------------------------------------

Countries Statistics

Using the same approach, you can create as many branches and their child nodes as you wish. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;
    
    tvwCountries->Left   = 12;
    tvwCountries->Top 	 = 12;
    tvwCountries->Width  = 220;
    tvwCountries->Height = 260;

    TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
    TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
    TTreeNode *nodAmerica = tvwCountries->Items->AddChild(nodRoot, "America");
    tvwCountries->Items->AddChild(nodRoot, "Asia");
    TTreeNode *nodEurope = tvwCountries->Items->AddChild(nodRoot, "Europe");

    tvwCountries->Items->AddChild(nodAfrica, "Senegal");
    tvwCountries->Items->AddChild(nodAfrica, "Botswana");
    tvwCountries->Items->AddChild(nodAfrica, "Ghana");
    tvwCountries->Items->AddChild(nodAfrica, "Morocco");

    tvwCountries->Items->AddChild(nodAmerica, "Canada");
    tvwCountries->Items->AddChild(nodAmerica, "Jamaica");
    tvwCountries->Items->AddChild(nodAmerica, "Colombia");

    tvwCountries->Items->AddChild(nodEurope, "Italy");
    tvwCountries->Items->AddChild(nodEurope, "Greece");
    tvwCountries->Items->AddChild(nodEurope, "Spain");
    tvwCountries->Items->AddChild(nodEurope, "England");
}
//---------------------------------------------------------------------------

Countries Statistics

The number of nodes in the TreeNodes objects is stored in the TreeNodes::Count property.

Practical LearningPractical Learning: Creating Child Nodes

  1. Under the Code editor, click the tab of the header file
  2. In the private section, declare a variable as follows:
    TList * AutoParts;
  3. Access the OnCreate event of the form and change it as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCentral::FormCreate(TObject *Sender)
    {
    	TDateTime Today = Date();
    	unsigned short Year, Month, Day;
    
    	AutoParts = new TList;
    	Today.DecodeDate(&Year, &Month, &Day);
    
    	TPartDescription * AutoPart = new TPartDescription(447093, 2002, L"Ford",
    				L"Escort SE L4 2.0", L"Engine Electrical",
    				L"Alternator 75amp  Remanufactured; w/ 75 Amp",
    				205.05);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(203815, 2006, L"Dodge",
    				L"Caravan SE L4 2.4", L"Cooling System",
    				L"Radiator Cap", 6.65);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(293047, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Thermostat Gasket", 4.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(990468, 2002, L"Honda",
    				L"Civic 1.7 EX 4DR", L"Exhaust",
    			L"Bolt & Spring Kit (Manifold outlet, Muffler Inlet)",
    				85.75);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(304158, 1996, L"Buick",
    				L"Regal Custom V6 3.8", L"Fuel Injection",
    				L"Fuel Injector", 82.75);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(807245, 2004, L"Acura",
    				L"MDX 3.5 4WD", L"Driveshaft & Axle",
    			L"CV Boot Clamp 7 x 750mm; 1 Large + 1 Small Clamp",
    				1.60);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(203485, 2001, L"Ford",
    				L"Taurus LX V6 3.0", L"Fuel Injection",
    			L"Oxygen Sensor OE Style 4Wire; Front; 2 Required",
    				52.65);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(248759, 1999, L"Jeep",
    				L"Wrangler Sahara", L"Air Intake",
    				L"Air Filter AirSoft Panel", 7.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(202848, 1998, L"Honda",
    				L"Accord 2.3 LX 4DR", L"Air Intake",
    				L"Air Filter", 12.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(932759, 2006, L"Kia",
    				L"Rio 1.6DOHC16V 4-DR", L"Cooling System",
    				L"Thermostat", 14.45);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(304975, 2000, L"Honda",
    				L"Civic 1.6 EX 4DR", L"Suspension",
    				L"Ball Joint; Front Lower; 2 per car", 40.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(208450, 2003, L"Chevrolet",
    				L"Monte Carlo LS V6 3.4", L"Fuel Injection",
    				L"Oxygen Sensor OE connector; Rear", 65.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(209480, 2002, L"Ford",
    				L"Focus SE DOHC L4 2.0", L"Steering",
    				L"Steering Rack Remanufactured", 170.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(203495, 2004, L"Honda",
    				L"Civic 1.7 EX 4DR", L"Climate Control",
    				L"A/C Clutch; OE compressor = Sanden", 184.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(203480, 2007, L"Toyota",
    				L"Corolla", L"Air Intake",
    				L"Air Filter", 12.65);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(109379, 2005, L"Volvo",
    				L"S40 2.5L T5 AWD", L"Fuel Delivery",
    			L"Fuel Filter; Early Design; Outer Diameter = 55mm",
    				30.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(935794, 2002, L"Ford",
    				L"Escape XLS 4WD", L"Brake",
    				L"Brake Caliper Remanufactured; Front Right",
    				65.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(203485, 2006, L"BMW",
    				L"325i", L"Climate Control",
    				L"AC High Pressure Side Switch",
    				49.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(204875, 1996, L"Chevrolet",
    				L"Monte Carlo Z34 V6 3.4", L"Fuel Delivery",
    				L"Fuel Filter", 8.05);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(937485, 2007, L"Toyota",
    			L"Camry V6", L"Air Intake", L"Air Filter", 12.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(294759, 2001, L"Ford",
                    L"Escape XLT 4WD", L"Air Intake",
    				L"Air Filter Panel", 7.25);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(297495, 2003, L"Honda",
    				L"Civic 1.7 EX 4DR", L"Brake",
                    L"Brake Caliper Reman; w/ ProAct Pads; Front Right",
    				82.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(794735, 2006, L"BMW",
    				L"325i", L"Climate Control",
                    L"Cabin Air/Pollen Filter; With Activated Carbon",
    				28.05);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(937485, 2007, L"Toyota",
    				L"Corolla", L"Body Electrical",
                    L"Halogen  SilverStar; 12V 65W; inner-high beam",
    				22.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(492745, 2005, L"Ford",
    				L"Focus ZX3 L4 2.0", L"Air Intake",
    				L"Fuel Injection Perf Kit", 342.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(937005, 2004, L"Acura",
                    L"MDX 3.5 4WD", L"Driveshaft & Axle",
    		L"CV Boot Clamp 7 x 750mm; For Large End of Boot; inner boot",
    				1.60);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(293749, 2004, L"Acura",
    				L"MDX 3.5 4WD", L"Driveshaft & Axle",
    				L"Axle Nut 24mm x 1;5; rear ",
    				2.35);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(920495, 2006, L"BMW",
                    L"325i", L"Climate Control",
    				L"Adjustable Telescoping Mirror", 7.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(204075, 2004, L"Acura",
                    L"MDX 3.5 4WD", L"Driveshaft & Axle",
                    L"Wheel Bearing; Rear; 1 per wheel",
    				70.15);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(979304, 2000, L"Toyota",
                    L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Thermostat Housing", 20.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(300456, 2004, L"Acura",
    				L"MDX 3.5 4WD", L"Driveshaft & Axle",
                    L"Wheel Bearing; Front; 1 per wheel",
    				66.65);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(404860, 2001, L"Ford",
    				L"Taurus LX V6 3.0", L"Suspension",
                    L"Shock Absorber GR2; Rear; Wagon only",
    				39.40);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(585688, 2007, L"Buick",
    				L"Lacrosse CXS V6 3.6", L"Brake",
    				L"Climate Control", 10.65);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(739759, 2001, L"Ford",
                    L"Taurus LX V6 3.0", L"Suspension",
    				L"Shock Absorber GasaJust; Rear; Wagon only",
    				30.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(927495, 2005, L"Volvo",
                    L"S40 2.5L T5 AWD", L"Engine Mechanical",
    			L"Timing Belt Idler Pulley Original Equipment INA",
    				65.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(979374, 2000, L"Toyota",
                    L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Thermostat Gasket", 4.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(542347, 2007, L"Buick",
    				L"Lacrosse CXS V6 3.6", L"Brake",
    			L"Brake Pad Set ProACT Ceramic w/Shims; Front", 80.05);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(683064, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
                    L"Radiator Hose; Upper", 103.75);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(248759, 1999, L"Jeep",
                    L"Wrangler Sahara", L"Air Intake",
    				L"Air Filter", 50.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(973974, 2007, L"Toyota",
                    L"Corolla", L"Air Intake",
                    L"Air Mass Meter; W/o Housing; Meter/sensor only",
    				134.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(285800, 2001, L"Ford",
                    L"Escape XLT 4WD", L"Transmission",
    				L"AT Filter", 34.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(207495, 2007, L"Toyota",
    				L"Corolla", L"Body Electrical",
    			L"Headlight Bulb; 12V 65W; inner-high beam", 9.35);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(566676, 2000, L"Toyota",
                    L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Auxiliary Fan Switch", 42.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(304950, 2007, L"Toyota",
                    L"Corolla", L"Body Electrical",
    				L"Headlight Bulb; 12V 51W; outer", 7.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(797394, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Water Flange Gasket", 0.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(910203, 2007, L"Buick",
                    L"Lacrosse CXS V6 3.6", L"Suspension",
    				L"Strut Mount Inc; Sleeve; Rear Right", 80.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(790794, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Radiator Hose; Lower", 9.45);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(970394, 2007, L"Buick",
    				L"Lacrosse CXS V6 3.6", L"Suspension",
                    L"Coil Spring Insulator; Front Lower",
    				14.55);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(290840, 2005, L"Volvo",
    				L"S40 2.5L T5 AWD", L"Engine Mechanical",
                    L"Rod Bearing Set 1 per Rod; Standard; Reqs. 5-per Engine",
    				26.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(209704, 2007, L"Toyota",
    				L"Corolla", L"Body Electrical",
    				L"Wiper Blade Excel+; Front Right", 7.25);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(200368, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Radiator Drain Plug incl; gasket", 3.15);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(200970, 2005, L"Volvo",
                    L"S40 2.5L T5 AWD", L"Engine Mechanical",
                    L"Reference Sensor; Flywheel Engine Speed",
    				62.05);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(542347, 2007, L"Buick",
    				L"Lacrosse CXS V6 3.6", L"Air Intake",
    				L"Air Filter", 50.25);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(927045, 2001, L"Ford",
    				L"Escape XLT 4WD", L"Air Intake",
    				L"Air Filter", 62.95);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(990659, 2000, L"Toyota",
    				L"RAV4 2WD/4-DOOR", L"Cooling System",
    				L"Radiator OE Plastic tank", 136.85);
    	AutoParts->Add(AutoPart);
    
    	AutoPart = new TPartDescription(440574, 2007, L"Buick",
                    L"Lacrosse CXS V6 3.6", L"Suspension",
                    L"Strut Mount Inc; Sleeve; Rear Left",
    				80.80);
    
    	// The root node
    	TTreeNode * nodRoot = tvwCarIdentification->Items->Add(NULL,
    			 L"College Park Auto-Parts");
    
    	// Showing the years nodes
    	for(int i = Year + 1; i >= 1960; i--)
    		tvwCarIdentification->Items->AddChild(nodRoot, IntToStr(i));
    
    	// Showing the makes nodes
    	// Get ready to check each node under the root
    	for(int a = 0; a < nodRoot->Count; a++)
    	{
    		// Get a reference to each node (year) of the root
    		TTreeNode * NodeYear = nodRoot->Item[a];
    		// Create a list of makes
    		TStringList * ListOfMakes = new TStringList;
    
    		// Check each auto part
    		for(int b = 0; b < AutoParts->Count; b++)
    		{
    			// Get a reference to the current auto part from the collection
    			TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[b]);
    
    			// Find out if the year selected is found in the auto parts list
    			if( NodeYear->Text.ToInt() == Part->CarYear )
    			{
    				// If it is, check if our list of makes already contains the current make.
    				// If it doesn't, then add it to the list of makes of the current year
    				if( ListOfMakes->IndexOf(Part->Make) == -1 )
    					ListOfMakes->Add(Part->Make);
    			}
    		}
    
    		// Now that we have a list of makes, create a node for each in the current year
    		for(int k = 0; k < ListOfMakes->Count; k++)
    			tvwCarIdentification->Items->AddChild(NodeYear, ListOfMakes->Strings[k]);
    	}
    
    	// Showing the models nodes
    	for(int a = 0; a < nodRoot->Count; a++)
    	{
    		TTreeNode * NodeYear = nodRoot->Item[a];
    
    		for(int b = 0; b < NodeYear->Count; b++)
    		{
    			TTreeNode * NodeMake = NodeYear->Item[b];
    			TStringList * ListOfModels = new TStringList;
    
    			for(int c = 0; c < AutoParts->Count; c++)
    			{
    				TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[c]);
    
    				if( (NodeYear->Text.ToInt() == Part->CarYear) &&
    					(NodeMake->Text == Part->Make) )
    				{
    					if( ListOfModels->IndexOf(Part->Model) == -1 )
    						ListOfModels->Add(Part->Model);
    				}
    			}
    
    			for(int k = 0; k < ListOfModels->Count; k++)
    				tvwCarIdentification->Items->AddChild(NodeMake, ListOfModels->Strings[k]);
    		}
    	}
    
    	// Showing the categories nodes
    	for(int a = 0; a < nodRoot->Count; a++)
    	{
    		TTreeNode * NodeYear = nodRoot->Item[a];
    
    		for(int b = 0; b < NodeYear->Count; b++)
    		{
    			TTreeNode * NodeMake = NodeYear->Item[b];
    
    			for(int c = 0; c < NodeMake->Count; c++)
    			{
    				TTreeNode * NodeModel = NodeMake->Item[c];
    				TStringList * ListOfCategories = new TStringList;
    
    				for(int d = 0; d < AutoParts->Count; d++)
    				{
    					TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[d]);
    
    					if( (NodeYear->Text.ToInt() == Part->CarYear) &&
    						(NodeMake->Text == Part->Make) &&
    						(NodeModel->Text == Part->Model) )
    					{
    						if( ListOfCategories->IndexOf(Part->Category) == -1 )
    							ListOfCategories->Add(Part->Category);
    					}
    				}
    
    				for(int k = 0; k < ListOfCategories->Count; k++)
    					tvwCarIdentification->Items->AddChild(NodeModel, ListOfCategories->Strings[k]);
    			}
    		}
    	}
    }
    //---------------------------------------------------------------------------
  4. Execute the application to see the result
     
    College Park Auto Parts
  5. Close the form and return to your programming environment
 
 
 

The Siblings of a Node

If you create a node and add it to a branch that already contains another node, the new node is referred to as a sibling to the existing child node. To create a new node that would be a sibling to an existing node, you can call the TTreeNodes::Add() method we used to create the root node. If you want to specify that the new node would be a sibling to an existing node, pass the existing node as the first argument to this method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;
    tvwCountries->Left   = 10;
    tvwCountries->Top    = 12;
    tvwCountries->Width  = 220;
    tvwCountries->Height = 90;

    TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
    TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
    tvwCountries->Items->Add(nodAfrica, "America");
    tvwCountries->Items->Add(nodAfrica, "Asia");
    tvwCountries->Items->Add(nodAfrica, "Europe");
}
//---------------------------------------------------------------------------

Countries Statistics

Notice that America, Asia, and Europe are siblings to Africa, whose node was passed as the first argument to the Add() method.

When you call the TreeNodes::Add() method to create a node, the new branch is added at the end of the list of its siblings. If you want, you can add a new child somewhere in the tree. To do this, you would call the TreeNode::Insert() method. Its syntax is:

TTreeNode* __fastcall Insert(TTreeNode* Node, const AnsiString S);

The first argument to this method is a reference to the node that will the sibling to the new node. The second argument is the text that the new node will display. To perform the same operation, you can call the TTreeNodes::InsertNode() method. Its syntax is:

TTreeNode* __fastcall InsertNode(TTreeNode* Node,
 				 TTreeNode* Sibling,
				 const AnsiString S,
				 void * Ptr);

The Selected Node

Besides looking at a node, probably the primary action a user performs on a tree is to select an item. To select a node in the tree, the user can click it. To programmatically select a node, assign its reference to the TreeView::Selected property:

__property Comctrls::TTreeNode * Selected = {read=GetSelected,write=SetSelected};

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TTreeView* tvwCountries = new TTreeView(this);
	tvwCountries->Parent = this;

	tvwCountries->Left   = 12;
	tvwCountries->Top    = 12;
	tvwCountries->Width  = 220;
	tvwCountries->Height = 90;

	TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
	TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
	TTreeNode *nodAmerica = tvwCountries->Items->Add(nodAfrica, "America");
	tvwCountries->Items->Add(nodAfrica, "Asia");
	tvwCountries->Items->Add(nodAfrica, "Europe");

	tvwCountries->Selected = nodAmerica;
}
//---------------------------------------------------------------------------

Countries Statistics

After selecting a node, the tree view indicates the item selected by highlighting it. In the above picture, the America node is selected.

Practical LearningPractical Learning: Using the Selected Node

  1. On the form, click the tree view
  2. In the Object Inspector, click Events
  3. In the Events section, double-click the right side on OnChange
  4. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCentral::tvwCarIdentificationChange(TObject *Sender,
    							TTreeNode *Node)
    {
        if(Node->Level == 4 )
    	lvwAvailableParts->Items->Clear();
    
        for(int i = 0; i < AutoParts->Count; i++)
        {
    	TPartDescription * Part =
    		reinterpret_cast<TPartDescription *>(AutoParts->Items[i]);
    
    	if( (Part->Category == Node->Text) &&
    	    (Part->Model == Node->Parent->Text) &&
    			(Part->Make == Node->Parent->Parent->Text) &&
    			(Part->CarYear == Node->Parent->Parent->Parent->Text) )
    	{
    		TListItem * lviAutoPart = lvwAvailableParts->Items->Add();
    
    		lviAutoPart->Caption = Part->PartNumber;
    		lviAutoPart->SubItems->Add(Part->PartName);
    		lviAutoPart->SubItems->Add(Part->UnitPrice);
    	}
       }
    }
    //---------------------------------------------------------------------------
  5. Return to the form
  6. Press F9 to execute
     
    College Park Auto Parts
     
    College Park Auto Parts
  7. Close the form and return to your programming environment

The Selected Nodes

By default, the user can select only one item from a time in the tree view. If you want to user to be able to select more than one node, set the TTreeView::MultiSelect property to true:

__property bool MultiSelect = {read=FMultiSelect,write=SetMultiSelect};

Its default value is false. If you allow the user to select more than one node, you can then control how a multiple selection can be performed. This is done using the TTreeView::MultiSelectStyle property:

__property System::Set<Comctrls::TMultiSelectStyles,0,3> MultiSelectStyle = 
{
	read=FMultiSelectStyle,
	write=SetMultiSelectStyle
};

Whether the user selects one or more items, the list of selected nodes is stored in the TTreeView::Selections property, which is a collection:

__property Comctrls::TTreeNode * Selections = {read=GetSelection};

Each member of this collection is an object of type TTreeNode. When only one node is selected, which is usually the case, you can get its reference from its index of the Selections property. The code to get this information would be as follows:

TTreeNode *nodSel = tvwCountries->Selections[0];

If you had allowed the user to select more than one node, you can get a reference for each using its index in the Selected property.

Node Edition

After locating a node, the user may want to change its text. To change the string of a node, it must be put to edit mode. To do this, you can call the TTreeNodes::BeginUpdate() method. Its syntax is:

void __fastcall BeginUpdate(void);

When a node is in edit mode, the caret blinks in its edit box section. The user can then type a new string or edit the existing string. After setting the (new) string, the user can press Enter or may click somewhere. At this time, you need to indicate that the user has finished this operation. To do this, you can call the TTreeNodes::EndUpdate() method. Its syntax is:

void __fastcall EndUpdate(void);

Just before this method, you can check the content of the string that was added or edited. This allows you to accept or reject the change.

Node Location

To get a reference to the top most node of the tree view, you can access the value of the TTreeView::TopItem, which produces a TTreeNode object.

As mentioned already, the nodes of a tree view are stored in a collection of type TTreeNodes. Every time you create a new node, it occupies a position inside the tree. Each node is represented by the Item indexed property of this collection and each item is of type TTreeNode. Besides the Item property, the [] operator is overloaded in the TTreeNodes class to allow you to access any node using its index.

The first node of the tree has an index of 0 in the TTreeNodes::Item[] collection. Another technique you can use to get a reference to the first item is by calling the TTreeNodes::GetFirstNode() method. Its syntax is:

TTreeNode* __fastcall GetFirstNode(void);

The second node has an index of 1 in the TTreeNodes::Item[] collection and so on. You can use this property to access any node in the tree. Another technique you can use to get a reference to the first item is by calling the TTreeNodes::GetFirstNode() method. Its syntax is:

TTreeNode* __fastcall GetFirstNode(void);

The children of a node are stored in its TTreeNode::Item[] property, which is a collection. To get a reference to the first child of a node, you can access the item stored in TTreeNode::Item[0]. An alternative is to call its TTreeNode::GetFirstChild() method. Its syntax is:

TTreeNode* __fastcall getFirstChild(void);

In the same way, the TTreeNode class provides other methods to access the last child (GetLastChild()), the next sibling (GetNextSibling()), the next child (GetNextChild()), etc, nodes.

Another technique you can use to locate a node consists of using some coordinates. To do this, you can call the TreeView::GetNodeAt() method. Its syntax is:

TTreeNode* __fastcall GetNodeAt(int X, int Y);

To use this method, you must know the location or the x and y coordinates of the node. If you provide valid argumentation to this method, it returns a reference to the TTreeNode located at the argument.

Deleting Nodes

When a tree contains a few nodes, the user may want to delete some of them, for any reason. To remove a node, you can call the TTreeNodes::Delete() method. Its syntax is:

void __fastcall Delete(TTreeNode* Node);

This method expects a reference to the node you want to remove. If you are already at that node and you want to remove it, you can call the TTreeNode::Delete() method. Its syntax is:

void __fastcall Delete(void);

One of the characteristics of a tree in the real world is that, if you cut a branch, the other branches attached to it and their leaves are cut too. In the same way, if you call any of these Delete() methods to delete a node, its children would be deleted too. If you want to remove (only) the children of an item, you can call its TTreeNode::DeleteChildren() method. Its syntax is:

void __fastcall DeleteChildren(void);

To remove all nodes of a tree view, you can call the TTreeNodes::Clear() method. Its syntax is:

void __fastcall Clear(void);

This method is used to get rid of all nodes of a tree.

Visual Feedback of Nodes

 

Hot Tracking

In order to select an item, the user must click it or navigate to it using the keyboard. Alternative, if you want, you can cause the item to be underlined when the mouse passes over it:

Countries Statistics

To produce this effect, you can set to true the TTreeView::HotTrack Boolean property:

__property bool HotTrack = {read=FHotTrack,write=SetHotTrack};

Its default value is false. Here is an example of using it:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TTreeView* tvwCountries = new TTreeView(this);
	tvwCountries->Parent = this;

	tvwCountries->Left   = 12;
	tvwCountries->Top    = 12;
	tvwCountries->Width  = 220;
	tvwCountries->Height = 90;

	tvwCountries->HotTrack = True;

	TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
	TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
	TTreeNode *nodAmerica = tvwCountries->Items->Add(nodAfrica, "America");
	tvwCountries->Items->Add(nodAfrica, "Asia");
	tvwCountries->Items->Add(nodAfrica, "Europe");
}
//---------------------------------------------------------------------------

The Intermediary Lines of Related Nodes

As mentioned already, a tree view appears as a list of items arranged like a tree. This implies a relationship of parent-child between two items in the control. To indicate this relationship between two nodes, a line is drawn from one to another. Based on this, a line from a node on top to another node under it indicates that the one on top is the parent to the one under it.

The presence or absence of the lines among related nodes is controlled by the TTreeView::ShowLines Boolean property. By default, this property is set to true. If this property is set to false, the lines among the nodes would not display. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TTreeView* tvwCountries = new TTreeView(this);
    tvwCountries->Parent = this;
    
    tvwCountries->Left = 10;
    tvwCountries->Top = 12;
    tvwCountries->Width = 220;
    
    tvwCountries->ShowLines = false;

    TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
    TTreeNode *nodContinent = tvwCountries->Items->AddChild(nodRoot, "Africa");
    tvwCountries->Items->Add(nodContinent, "America");
    tvwCountries->Items->Add(nodContinent, "Asia");
    tvwCountries->Items->Add(nodContinent, "Europe");
}
//---------------------------------------------------------------------------

The Root Lines

If you create a tree that has more than one root, a line is drawn among those root nodes. Here is an example:

Countries Statistics

The presence or absence of this type of line is controlled by the TTreeView::ShowRoot Boolean property:

__property bool ShowRoot = {read=FShowRoot,write=SetRootStyle};

Its default value is true. If you set its value to false, these lines would not appear.

Node Indentation

Indentation is the ability for a child node to be aligned to the right with regards to its parent. The general distance from the left border of the parent to the left border of the children is partially controlled by the TTreeView::Indent property which is an integer. If the default distance doesn't suit you, you can change it by assigning a positive number to the control's Indent property.

Full Row Selection

When the user clicks an item, that node becomes highlighted for the length of its string. If you want, you can show the highlighting on the selected node but from the left to the right borders of the tree view. To support this, the TCustomTreeView class provides the RowSelect Boolean property:

__property int Indent = {read=GetIndent,write=SetIndent};

The default value of this property is False. For the TTCustomTreeView::RowSelect property to work, the ShowLines property must be set to False. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TTreeView* tvwCountries = new TTreeView(this);
	tvwCountries->Parent = this;

	tvwCountries->Left   = 12;
	tvwCountries->Top    = 12;
	tvwCountries->Width  = 220;
	tvwCountries->Height = 90;

	tvwCountries->ShowLines = False;
	tvwCountries->RowSelect = True;

	TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
	TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
	TTreeNode *nodAmerica = tvwCountries->Items->Add(nodAfrica, "America");
	tvwCountries->Items->Add(nodAfrica, "Asia");
	tvwCountries->Items->Add(nodAfrica, "Europe");
}
//---------------------------------------------------------------------------

Countries Statistics

Hiding Selection After Losing Focus

We saw that, to select an item, the user can click it. If the user clicks another control, the node that was selected in the tree view loses its highlighting because the control has lost focus. When the focus moves to another control, if you want the selected node of the tree view to preserve its highlighting, set to false the TTreeView::HideSelection Boolean property:

__property bool HideSelection = {read=FHideSelection,write=SetHideSelection};

Its default value is true.

The + and - Buttons

In previous sections, we saw that some nodes have children and some don't. When a node has at least one child, the node indicates this by displaying a + button. If the user clicks the + button, the node expands, displays a list of its children, and the button becomes -. The presence or absence of the + and - buttons is controlled by the TTreeView::ShowButtons Boolean property:

__property bool ShowButtons = {read=FShowButtons,write=SetButtonStyle};

By default, this property is set to true. If you don't want the parent nodes to display the + or - button, set this property to false.

Expanding and Collapsing Tree Nodes

When a node displays a + button and the user clicks that button, the node displays its child(ren). This action is referred to as expanding the node. To programmatically expand a node, call its TTreeNode::Expand() method. Its syntax is:

void __fastcall Expand(bool Recurse);

This method can be called to expand the node that calls it. If you want to expand only the node but not its children that have their own children, pass the Recurse argument as false. To expand a node and its children that have nodes, pass the argument as true.

To find out if a node is expanded, check the value of its TTreeNode::Expanded property:

__property bool Expanded = {read=GetExpanded,write=SetExpanded};

To expand other nodes of the tree view, the user can continue clicking each node that has a + button as necessary. To programmatically expand all nodes of a tree view, call its TTreeView::FullExpand() method. Its syntax is:

void __fastcall FullExpand(void);

If a node is displaying a - button, it indicates that it is showing the list of its children. To hide the list, the user can click the - button. This action is referred to as collapsing the node. To programmatically collapse a node, call its TTreeNode::Collapse() method whose syntax is:

void __fastcall Collapse(bool Recurse);

If you want to collapse only the node but not its children that are already expanded, pass the argument as false. If you want to collapse the node and its children that have their own children, pass the argument as true.

The user can continually click the - button of each node that is expanded to collapse them. To programmatically collapse all nodes of a tree view, call its TTreeView::FullCollapse() method. Its syntax is:

void __fastcall FullCollapse();

Tree Nodes and Check Boxes

Besides the strings (and some small pictures as we will see later), the nodes of a tree view can display a check box on their left side. To display check boxes on the items of a tree view, call the SetWindowLong() function and specify that you want to add the TVS_CHECKBOXES style. This can be done as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TTreeView* tvwCountries = new TTreeView(this);
	tvwCountries->Parent = this;

	tvwCountries->Left   = 12;
	tvwCountries->Top    = 12;
	tvwCountries->Width  = 140;
	tvwCountries->Height = 270;

	LONG GWLTreeView = GetWindowLong(tvwCountries->Handle, GWL_STYLE);
	SetWindowLong(tvwCountries->Handle, GWL_STYLE,
					GWLTreeView | TVS_CHECKBOXES);

	TTreeNode *nodRoot = tvwCountries->Items->Add(NULL, "World");
	TTreeNode *nodAfrica = tvwCountries->Items->AddChild(nodRoot, "Africa");
	TTreeNode *nodAmerica = tvwCountries->Items->AddChild(nodRoot, "America");
	tvwCountries->Items->AddChild(nodRoot, "Asia");
	TTreeNode *nodEurope = tvwCountries->Items->AddChild(nodRoot, "Europe");

	tvwCountries->Items->AddChild(nodAfrica, "Senegal");
	tvwCountries->Items->AddChild(nodAfrica, "Botswana");
	tvwCountries->Items->AddChild(nodAfrica, "Ghana");
	tvwCountries->Items->AddChild(nodAfrica, "Morocco");

	tvwCountries->Items->AddChild(nodAmerica, "Canada");
	tvwCountries->Items->AddChild(nodAmerica, "Jamaica");
	tvwCountries->Items->AddChild(nodAmerica, "Colombia");

	tvwCountries->Items->AddChild(nodEurope, "Italy");
	tvwCountries->Items->AddChild(nodEurope, "Greece");
	tvwCountries->Items->AddChild(nodEurope, "Spain");
	tvwCountries->Items->AddChild(nodEurope, "England");
}
//---------------------------------------------------------------------------

Countries Statistics

If you equip the nodes with check boxes, the user can click an item to select it independently of the check box. The user can also click the check box, which would place a check mark in the box. Here are examples:

Countries Statistics

Tree Nodes and Icons

Each of the nodes we have used so far displayed text. To enhance the appearance of a node, besides its text, you can display a small icon to the left of its string. To do this, you must first create a list of images and store them in a TImageList object. After creating a tree view, if you plan to display an icon next to its nodes, first assign a TImageList value to its Images property.

To support pictures associated with items, the TTreeNode class is equipped with a property called ImageIndex:

__property int ImageIndex = {read=FImageIndex,write=SetImageIndex};

This property allows you to assign the intended image to the node.

Practical LearningPractical Learning: Associating Icons With Nodes

  1. In the Win32 section of the Tool Palette, click TImageList and click the form (anywhere)
  2. On the form, double-click the TImageList1 that was just added
  3. In Form1->ImageList1 ImageList dialog box, click Add
  4. Locate the resources that accompany these lessons
  5. Select to add globe1.ico, globe2.ico, clock1.ico, clock2.ico, car1.ico, car2.ico, book1.ico, book2.ico, tool1.ico, and tool2.ico
  6. Click OK
  7. In the form, click the tree view and, in the Object Inspector, set its Image property to ImageList1
  8. Press F12 to access the code of the form and change its OnCreate event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmCentral::FormCreate(TObject *Sender)
    {
        TDateTime Today = Date();
        unsigned short Year, Month, Day;
    
        AutoParts = new TList;
        Today.DecodeDate(&Year, &Month, &Day);
    
        . . . No Change
    
        // The root node
        TTreeNode * nodRoot = tvwCarIdentification->Items->Add(NULL,
    			 L"College Park Auto-Parts");
        nodRoot->ImageIndex    = 0;
        nodRoot->SelectedIndex = 1;
    
        // Showing the years nodes
        for(int i = Year + 1; i >= 1960; i--)
        {
    	TTreeNode * NodeYear = tvwCarIdentification->Items->AddChild(nodRoot, IntToStr(i));
    	NodeYear->ImageIndex    = 2;
    	NodeYear->SelectedIndex = 3;
        }
    
        // Showing the makes nodes
        // Get ready to check each node under the root
        for(int a = 0; a < nodRoot->Count; a++)
        {
    	// Get a reference to each node (year) of the root
    	TTreeNode * NodeYear = nodRoot->Item[a];
    	// Create a list of makes
    	TStringList * ListOfMakes = new TStringList;
    
    	// Check each auto part
    	for(int b = 0; b < AutoParts->Count; b++)
    	{
    	    // Get a reference to the current auto part from the collection
    	    TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[b]);
    
    	    // Find out if the year selected is found in the auto parts list
    	    if( NodeYear->Text.ToInt() == Part->CarYear )
    	    {
    		// If it is, check if our list of makes already contains the current make.
    		// If it doesn't, then add it to the list of makes of the current year
    		if( ListOfMakes->IndexOf(Part->Make) == -1 )
    			ListOfMakes->Add(Part->Make);
    	    }
    	}
    
    	// Now that we have a list of makes, create a node for each in the current year
    	for(int k = 0; k < ListOfMakes->Count; k++)
    	{
    	    TTreeNode * NodeMake = tvwCarIdentification->Items->AddChild(NodeYear, ListOfMakes->Strings[k]);
    	    NodeMake->ImageIndex    = 4;
    	    NodeMake->SelectedIndex = 5;
    	}
        }
    
        // Showing the models nodes
        for(int a = 0; a < nodRoot->Count; a++)
        {
    	TTreeNode * NodeYear = nodRoot->Item[a];
    
    	for(int b = 0; b < NodeYear->Count; b++)
    	{
    	    TTreeNode * NodeMake = NodeYear->Item[b];
    	    TStringList * ListOfModels = new TStringList;
    
    	    for(int c = 0; c < AutoParts->Count; c++)
    	    {
    		TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[c]);
    
    		if( (NodeYear->Text.ToInt() == Part->CarYear) &&
    		    (NodeMake->Text == Part->Make) )
    		{
    		    if( ListOfModels->IndexOf(Part->Model) == -1 )
    			ListOfModels->Add(Part->Model);
    		}
    	    }
    
    	    for(int k = 0; k < ListOfModels->Count; k++)
    	    {
    		TTreeNode * NodeModel = tvwCarIdentification->Items->AddChild(NodeMake, ListOfModels->Strings[k]);
    		NodeModel->ImageIndex    = 6;
    		NodeModel->SelectedIndex = 7;
    	    }
    	}
        }
    
        // Showing the categories nodes
        for(int a = 0; a < nodRoot->Count; a++)
        {
    	TTreeNode * NodeYear = nodRoot->Item[a];
    
    	for(int b = 0; b < NodeYear->Count; b++)
    	{
    	    TTreeNode * NodeMake = NodeYear->Item[b];
    
    	    for(int c = 0; c < NodeMake->Count; c++)
    	    {
    		TTreeNode * NodeModel = NodeMake->Item[c];
    		TStringList * ListOfCategories = new TStringList;
    
    		for(int d = 0; d < AutoParts->Count; d++)
    		{
    		    TPartDescription * Part = reinterpret_cast<TPartDescription *>(AutoParts->Items[d]);
    
    		    if( (NodeYear->Text.ToInt() == Part->CarYear) &&
    			(NodeMake->Text == Part->Make) &&
    			(NodeModel->Text == Part->Model) )
    		    {
    			if( ListOfCategories->IndexOf(Part->Category) == -1 )
    			    ListOfCategories->Add(Part->Category);
    		    }
    		}
    
    		for(int k = 0; k < ListOfCategories->Count; k++)
    		{
    		    TTreeNode * NodeCategory = tvwCarIdentification->Items->AddChild(NodeModel, ListOfCategories->Strings[k]);
    		    NodeCategory->ImageIndex    = 8;
    		    NodeCategory->SelectedIndex = 9;
    		}
    	    }
    	}
        }
    }
    //---------------------------------------------------------------------------
  9. Execute the application to test it
     
    College Park Auto Parts
     
    College Park Auto Parts
  10. Close the form and return to your programming environment
 
 
   
 

Home Copyright © 2010-2016, FunctionX