Home

Windows Controls: The List View

   

Introduction to the List View

 

Description

A list view is a list of items that presents many options:

  • The items can each appear as a large icon and a label
     
    List View: Large Icons
  • The items can each appear as a small icon and a label:
     
    List View: List
  • The items can be made to show some details (related-information) each:
      
    List View Style: Small Icons

Practical LearningPractical Learning: Introducing the List View Control

  1. Start Embarcadero RAD Studio
  2. To create a new application, on the main menu, click File -> New -> VCL Forms Application - C++Builder
  3. In the Object Inspector, change the following properties:
    Caption: Altair Realtors - Properties Listing
    Name:    frmPropertiesListing
    Position: poScreenCenter
  4. To save the project, on the main menu, click File -> Save All
  5. Click New Folder
  6. Type AltairRealtors1 as the name of the folder and press Enter twice to display the contents of that folder
  7. Change the unit file to AltairRealtors
  8. Click Save
  9. Change the project name to PropertiesListing
  10. Click Save

List View Creation

To support the list view control, the VCL provides a class named TListView. TListView implements the TCustomListView class. The TCustomListView class derives from TCustomMultiSelectListControl, which itself is based on the TCustomListControl class that deries from TWinControl:

TListView Inheritance

 

To visually add a list view to an application, in the Win32 section of the Tool Palette, click TListView TListView and click the form. To programmatically create a list view, declare a variable of type TListView, use the new operator to instantiate. Make sure you specify its owner and parent. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
	TListView * lvwCountries = new TListView(this);
	lvwCountries->Parent = this;
}
//---------------------------------------------------------------------------

After this declaration, an empty rectangular control is created and added to your application. You can then start populating it.

Practical LearningPractical Learning: Creating a List View

  1. On the Tool Palette, click Win32
  2. Click TListView TListView
  3. Click the form
  4. While the list view is still selected on the form, in the Object Inspector, change its Name to lvwProperties

      Altair Realtors

Introduction to the Items of a List View

 

The Collection of List View Items

To hold its list of items, the TCustomListView class is equipped with a property named Items, which is of type TListViewItemCollection:

__property Comctrls::TListItems * Items = {read=FListItems,write=SetItems};

The TListItems class is derived from TPersistent. As you can see, TListItems is a collection class. Each item is of type TListItem. The TListItem class is derived from TPersistent.

Visually Creating the Items of a List View

To visually create the items of a list view, you can use the ListView Items Editor. To access it, after adding a list view object to your application:

  • On the form, right-click the list view and click Items Editor...
  • While the list view is selected on the form, in the Object Inspector, click Items, and click its ellipsis button

In both cases, the ListView Items Editor would come up:

ListView Item Editor

At design time and in the ListView Item Editor, to create a new item, you can click the New Item button.

Practical LearningPractical Learning: Adding Items to a List View

  1. On the form, right-click the list view and click Items Editor ...
  2. Click New Item
  3. In the Caption box, type 2927-4209
  4. Click New Item
  5. In the right list, click Caption and type 7212-4748
     
    ListView Item Editor
  6. Click OK

Programmatically Creating an Item

To help you programmatically create a new item, the TListItems class is equipped with the Add() method. The TListItems::Add() method returns a TListItem object. Its syntax is:

Comctrls::TListItem * __fastcall Add(void);

The TListItems::Add() method allows you to create a TListItem object without giving any detail about that object. If you want to use that object later in your code, you should (must) get a reference to the returned value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
	TListView * lvwCountries = new TListView(this);
	lvwCountries->Parent = this;

	TListItem * Country = NULL;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 350;
	lvwCountries->Height = 160;

	Country = lvwCountries->Items->Add();
}
//---------------------------------------------------------------------------

After calling the TListItems::Add() method, you can use the TListItem value it returns to manage the item.

The Caption of an Item

The most obvious aspect of a list view item is the string it displays. This is its caption. It is represented in the TListItem class by the Caption property:

__property System::UnicodeString Caption = {read=FCaption,write=SetCaption};

To visually specify the caption of an item, in the ListView Item Editor, after clicking New Item, enter the desired string in the Caption edit box. To programmatically the caption of an item, assign the desired string to its Caption property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
    TListView * lvwCountries = new TListView(this);
    lvwCountries->Parent = this;

    TListItem * Country = NULL;

    lvwCountries->Left = 12;
    lvwCountries->Top  = 12;
    lvwCountries->Width  = 350;
    lvwCountries->Height = 160;

    Country = lvwCountries->Items->Add();
    Country->Caption = L"Egypt";
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Creating List View Items

  1. To create a new form, on the main menu, click File -> New -> Form - C++Builder
  2. In the Object Inspector, change the following properties:
    BorderStyle: bsDialog
    Caption: Altair Realtors - Property Editor
    Name:    frmPropertyEditor
    Position: poScreenCenter
  3. To save the form, on the Standard toolbar, click the Save All button
  4. Change the Name to PropertyEditor
  5. Click Save
  6. In the Dialogs section of the Tool Palette, click TOpenPictureDialog TOpenPictureDialog
  7. Click the form
  8. In the Object Inspector, change its name to dlgPicture
  9. Design the form as follows:
     
    Altair Realtors
    Control Caption Name   Other Properties
    TLabel Label Property Type:      
    TComboBox TComboBox   cbxPropertyTypes   Style: csDropDownList
    Items: Condominium
    Townhouse
    Single Family
    Unknown
    TLabel Label City:      
    TEdit TEdit   edtCity    
    TLabel Label State:      
    TComboBox ComboBox   cbxStates   Style: csDropDownList
    Items:
    AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY
    TLabel Label Stories:      
    TEdit TEdit   edtStories    
    TLabel Label Year Built:      
    TEdit TEdit   edtYearBuilt    
    TLabel Label Bedrooms:      
    TEdit TEdit   edtBedrooms 0  
    TLabel Label Bathrooms:      
    TEdit TEdit   edtBathrooms 0.00  
    TLabel Label Property #:      
    TEdit TEdit   edtPropertyNumber   Enabled: False
    TLabel Label Condition:      
    TComboBox Combo Box   cbxConditions   Style: csDropDownList
    Items:
    Excellent
    Good Shape
    Needs Fixing
    TLabel Label Market Value:      
    TEdit TEdit   edtMarketValue 0.00  
    TLabel Label Status:      
    TComboBox Combo Box   Status   Style: csDropDownList
    Items:
    Unspecified
    Available
    Sold
    TBitBtn   btnPicture Picture...  
    TImage TImage   imgProperty    
    TBitBtn       Kind: bkOK
    TBitBtn       bkOK: bkCancel
  10. Double-click an unoccupied area of the form
  11. Return to the form
  12. Double-click the Picture button
  13. Click the PropertyEditor.h tab to access the header file
  14. Declare a public UnicodeString variable named PictureFile
    public:		// User declarations
    	TFileName PictureFile;
    	__fastcall TfrmPropertyEditor(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TfrmPropertyEditor *frmPropertyEditor;
    //---------------------------------------------------------------------------
    #endif
  15. Click the PropertyEditor.cpp tab and change the file as follows:
    //---------------------------------------------------------------------------
    __fastcall TfrmPropertyEditor::TfrmPropertyEditor(TComponent* Owner)
    	: TForm(Owner)
    {
    	PictureFile = L"";
    }
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertyEditor::btnPictureClick(TObject *Sender)
    {
        if( dlgPicture->Execute() )
        {
    	imgProperty->Picture->LoadFromFile(dlgPicture->FileName);
    	PictureFile = dlgPicture->FileName;
        }
    }
    //---------------------------------------------------------------------------
  16. Display the first form
  17. On the main menu, click File -> User Unit...
  18. Click the item in the window
  19. Click the Header radio button and click OK

Introduction to List View Groups

 

Overview

To better organize the items of a list view, you can put them in groups. Each group can hold a different set of items or a different number of items, but all items must be of the same type.

To support groups, the TListView class is equipped with a property named Groups. This property is based on a class named TListGroups:

__property Comctrls::TListGroups * Groups = {read=FListGroups,write=SetListGroups};

TListGroups is a classic collection class that is derived TCollection.

Creating a Group of Items

Each member of the TListGroups collection is of type TListGroup. The TListGroup class derived from TCollectionItem.

To visually create a group:

  • On the form, right-click the list view and click Groups Editor ...
  • While the list view is selected on the form, in the Object Inspector, click Groups, then click its ellisis button

Any of these actions would display the Editing ListView Group window:

ListViewGroup Collection Editor

To create a group:

  • Click the Add New button Add New
  • Right-click inside the window and click Add
  • Press Ins

This would a new group. You can use the Object Inspector to manage the group:

Object Inspector

Characteristics of a Group of Items

 

Showing or Hiding Groups

The groups of items can be viewed in vsIcon, vsReport, and vsSmallIcon styles but not in the vsList style. In the first three view styles, you have the option of showing or hiding the groups. To let you control this, the TCustomListView class provides the GroupView property:

__property bool GroupView = {read=FGroupView,write=SetGroupView};

If you set this Boolean property to False, which is its default, the items would not be grouped, even if you create groups. If you set this property to True, you must create or have groups and assign them to items.

The Caption of a Group

The items that belong to a group must make it obvious. To start, the group must identify itself, which is done with a title or label. The title of a group is also called a header. This is represented by the Header property, which is a UnicodeString:

__property System::UnicodeString Header = {read=FHeader,write=SetHeader};

Besides a title, a group has a way to be uniquely identified in the collection. This is represented by a property named GroupID:

__property int GroupID = {read=FGroupID,write=SetGroupID};

By default, when the title displays, it is aligned to the left. If you want, you can position it either to the center or the right section. The alignment is controlled by the HeaderAlign property that is of type TAlignment:

__property Classes::TAlignment HeaderAlign = {read=FHeaderAlign,write=SetHeaderAlign};

Applying a Group to an Item

After creating the groups, you can assign one to any item of your choice. To do this visually, display the ListView Item Editor. If you had not yet created the items, you must first do that. In the left list, click an item. In the Items Properties list, click the arrow of the Group combo box and select the desired group.

Practical LearningPractical Learning: Creating a Group of Items

  1. Right-click the form and click Groups Editor...
  2. In the Editor window, click the Add New button Add New
  3. In the Object Inspector, click Header and type Condominium
  4. Right-click incide the Editing window and click Add
  5. In the Object Inspector, click Header and type Townhouse
  6. Click inside the Editing window and press Ins
  7. In the Object Inspector, click Header and type Single Family
  8. Close the Editing window
  9. On the form, right-click the list view and click Items Editor...
  10. In the left list, click the first item if necessary.
    In the right section, click the arrow of the Group combo box and select Single Family
  11. In the left list, click the second item
  12. In the right list, click the arrow of the Group combo box and select Condominium
  13. Click OK

The Styles of a List View

 

Introduction

A list view provides various options to display its items. To support this, the TListView class is equipped with the ViewStyle property that is based on the TViewStyle enumeration:

__property Comctrls::TViewStyle ViewStyle = {read=FViewStyle,write=SetViewStyle};

Its members are:

enum TViewStyle{
	vsIcon,
	vsSmallIcon,
	vsList,
	vsReport
};
  • vsIcon: In this view, the control displays a list of items in the order they were added from left to right and from top to bottom. This means that items start displaying on the top left section of the control to the right. When the first line is filled and there are still items, the list continues to the next line. Each item uses an icon size of 32x32 pixels
  • vsSmallIcon: Like the vsIcon style, this view displays the list of items from the left to the right then to the next line if necessary. This time, each item uses a square region corresponding to a 16x16 pixel size
  • vsList: Like the vsSmallIcon option, each item uses a 16x16 pixel square to display. This time, the list is arranged in columns: the first item appears to the left side of the control. The next item (usually in order) appears under it, and so on. If there are more items to fit in one column, the list continues with a new column to the right of the previous one. This continues until the list is complete
  • vsReport: In this view, instead of showing just the string of the (main) item, each item can provide more detailed information in a column

As seen so far, you can use one of four different displays on a list view. Furthermore, you can give the user the ability to change the view. The different displays of the list view are controlled by the ViewStyle property of the TListView class. To specify the type of view to use, assign the desired member of the ViewStyle enumeration to the TListView::ViewStyle property. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
	TListView * lvwCountries = new TListView(this);
	lvwCountries->Parent = this;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 350;
	lvwCountries->Height = 160;
	
	lvwCountries->ViewStyle = vsReport;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Using View Styles

  1. Complete the design of the form as follows:
     
    Altair Realtors
    Control Anchors Caption Kind Name
               
    TListView DataGridView [akLeft,akTop,akRight,akBottom]     lvwProperties
    TCheckBox TCheckBox [akLeft,akBottom] Show Groups   chkShowGroups
    TButton TButton [akLeft,akBottom] L&arge Icon btnLargeIcon  
    TButton TButton [akLeft,akBottom] &Small Icon btnSmallIcon  
    TButton TButton [akLeft,akBottom] &List btnList  
    TButton TButton [akLeft,akBottom] &Report btnReport  
    TImage [akLeft,akRight,akBottom]     imgProperty
    TBitBtn [akRight,akBottom] New Property...   btnNewProperty
    TBitBtn [akRight,akBottom]   bkClose  
  2. Double-click the Large Icon button and implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::btnLargeIconClick(TObject *Sender)
    {
    	lvwProperties->ViewStyle = vsIcon;
    }
    //---------------------------------------------------------------------------
  3. Return to the form
  4. Double-click the Small Icon button and implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::btnSmallIconClick(TObject *Sender)
    {
    	lvwProperties->ViewStyle = vsSmallIcon;
    }
    //---------------------------------------------------------------------------
  5. Return to the form
  6. Double-click the List button and implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::btnListClick(TObject *Sender)
    {
    	lvwProperties->ViewStyle = vsList;
    }
    //---------------------------------------------------------------------------
  7. Return to the form
  8. Double-click the Report button and implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::btnReportClick(TObject *Sender)
    {
    	lvwProperties->ViewStyle = vsReport;
    }
    //---------------------------------------------------------------------------
  9. Return to the form
  10. Double-click the Show Groups check box
  11. Implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::chkShowGroupsClick(TObject *Sender)
    {
    	if( chkShowGroups->Checked == True )
    	{
    		lvwProperties->GroupView = True;
    	}
    	else
    	{
    		lvwProperties->GroupView = False;
    	}
    }
    //---------------------------------------------------------------------------
  12. Return to the form
  13. To execute the application, press F9
  14. Click the buttons on the form
  15. Close the form and return to your programming environment
  16. On the form, click the list view
  17. In the Object Inspector, click ViewStyle, then click the arrow of is combo box and select vsReport

The Icons of List View Items

A list view has built-in capability to display icons. The list view uses two sets of pictures in either 16x16 pixels or larger than that. This means that two icons would be associated to each item.

The first category of icons should have a 16x16 pixels size. These are referred to as small icons. In the second category of pictures, one of the types uses a 32x32 pixels size. In Microsoft Windows 7, the set of 32x32 pixels list is referred to as medium icons.

Before using the pictures, you should store them in image lists. Each set must be stored in its own TImageList object.

To support the various sets of icons, the TCustomListView class is equipped with a property named LargeImages for the 32x32-pixel icons:

__property Imglist::TCustomImageList * LargeImages = {read=FLargeImages,write=SetLargeImages};

The property used for small icons is named SmallImages, it is for the 16x16-pixel icons:

__property Imglist::TCustomImageList * SmallImages = {read=FSmallImages,write=SetSmallImages};

After creating both TImageList objects, you can assign each to the appropriate property. After assigning the icons to the list view items, each view style can use the appropriate item to display:

  • vsIcon: In this view, each item is displayed with its assigned 32x32 pixels icon. The string of the item displays under its corresponding icon:
     
    List View: Large Icons
  • vsList: Each item appears with the 16x16 pixels small icon to its left:
     
    List View: List
  • vsSmallIcon: Same as the vsList option
  • vsReport: Same as  the vsList

Practical LearningPractical Learning: Associating Icons With Nodes

  1. In the Win32 section of the Tool Palette, click TImageList TImageList
  2. Click the form
  3. In the Object Inspector, click Name and type imgLarge
  4. Click Height and type 32
  5. Click Width and type 32
  6. On the form, right-click imgLarge and click ImageList Editor...
  7. In the ImageList Editor, click Add
  8. From the resources that accompany these lessons, locate and select the Condominium.ico, the Townhouse.ico and the SingleFamily.ico icons
  9. Click OK
  10. In the Win32 section of the Tool Palette, click TImageList TImageList
  11. Click the form
  12. In the Object Inspector, click Name and type imgSmall
  13. On the form, right-click imgSmall and click ImageList Editor...
  14. In the ImageList Editor, click Add
  15. From the resources that accompany these lessons, locate and select the Condominium.ico, the Townhouse.ico, and the SingleFamily.ico icons
  16. Click OK
  17. On the form, click the list view
  18. In the Object Inspector, click LargeImages and set its value to imgLarge
  19. click SmallImages and set its value to imgSmall
  20. Click Items and click its ellipsis button
  21. In the left list, click the first item if necessary.
    In the Image Index edit box, reaplace the value with 2
  22. In the left list, click the second item
  23. Make sure the Image Index edit box has 0.
    Click OK
  24. To execute the application to test it, press F9
  25. Click the buttons to see the results
  26. Close the form and return to your programming environment
  27. On the form, click the list view
  28. In the Object Inspector, click ViewStyle, then click the arrow of is combo box and select vsReport

Introduction to the Columns of a List View

 

Overview

One of the characteristics of a list view is that it can provide more information about each item of its list. Each type of item can be equipped with its own list of sub-items. The view would appear as follows:

List View Style: Details

Before creating the sub-items of a list view, you may need to plan them first to identify the types of information you want to provide. To guide the user with the type of information that each item would display, you can create a column for each type.

Visually Creating Columns

To support columns, the TListView class is equipped with the Columns property. The Columns property is an object of type TListColumns:

__property Comctrls::TListColumns * Columns = {read=FListColumns,write=SetListColumns};

Thhe TListColumns class is derived from TCollection. Each column is of type TListColumn.

At design time, to create the columns:

  • On the form, right-click the list view and click Columns Editor ...
  • On the form, click the list view to select it, in the Object Inspector, click Columns, then click its ellispsis button

Any of these actions would display the Editing ListView Group window:

Editing ListView Columns

To create a group:

  • Click the Add New button Add New
  • Right-click inside the window and click Add
  • Press Ins

This would a new column. You can use the Object Inspector to manage it:

Object Inspector

Practical LearningPractical Learning: Visually Creating a Column

  1. On the form, right-click the list view and click Columns Editor...
  2. Click the Add New button Add New

Programmatically Creating Columns

To programmatically create a column, you can call the Add() method of the TCollection class. When calling that method, get its return value, which is a TListColumn object. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
	TListView * lvwCountries = new TListView(this);
	lvwCountries->Parent = this;

	TListColumn * colName = NULL;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 350;
	lvwCountries->Height = 160;

	colName = lvwCountries->Columns->Add();
}
//---------------------------------------------------------------------------

You can then use the returned value to manage the column.

If you call the Add() method to create a column, the new column is added at the end of the existing columns, unless it is the first column. If you don't want the new column to simply be created at the end of the other column(s), if any, you can call the TCollection::Insert() method.

 
 
 

Managing the Columns of a List View

 

The Caption of a Column

One of the most obvious characteristics of a column is its title. This is also referred to as its caption. It displays in the column header. The column is represented in TListColumn class by the Caption property:

__property System::UnicodeString Caption = {read=FCaption,write=SetCaption};

To visually specify the caption of a column, use the Object Inspector. To do this programmatically, assign the desired string to the TListColumn object. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnListViewClick(TObject *Sender)
{
	TListView * lvwCountries = new TListView(this);
	lvwCountries->Parent = this;

	TListColumn * colName = NULL;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 350;
	lvwCountries->Height = 160;
	lvwCountries->ViewStyle = vsReport;

	colName = lvwCountries->Columns->Add();
	colName->Caption = L"Country Name";
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Setting the Caption of a Column

  • While the new item is still selected in the Editing window, in the Object Inspector, click Caption and type Property #

The Caption Alignment

By default, the caption of a column aligns to the left. Alternatively, you can position it to the center or the right. This is controlled by the Alignment property:

__property Classes::TAlignment Alignment = {read=FAlignment,write=SetAlignment};

The Width of a Column

The width of a column is controlled by the Width:

__property int Width = {read=GetWidth,write=SetWidth};

Practical LearningPractical Learning: Creating Columns

  1. In the Editing window, while the new item is still selected, in the Object Inspector, click Width and type 80
  2. Using the Add New button Add New of the Editing window and the Object Inspector, create the other columns as follows:
     
    Alignment Caption Width
      Property # 80
      Property Type 85
      City 90
    taCenter State 40
    taRightJustify Stories 45
    taCenter Year Built 60
    taRightJustify Beds 40
    taRightJustify Baths 40
      Condition 70
      Status 60
    taRightJustify Value 70
  3. Close the Editing window
  4. Press F9 to execute
  5. Close the form and return to your programming environment

The Number of Columns of a List View

As reviewed above, the columns of a list view are stored in a TCollection collection. To know the number of columns of a list view, you can check its TCollection::Count property.

Deleting Columns

If you don't need a column any more, you can delete it. In the same way, you can delete all columns of a list view. To delete a TListColumn object, you can call the TCollection::Delete() method.

To delete all columns of a list view, you can call the TCollection::Clear() method.

Using a List View

 

Selecting an Item

As mentioned previously, a list view is made of a list of items. An item can be identified by its index:

  • On a large image or a small image style, the item on the top-left side has an index of 0. The second item from the left has an index of 1, and so on, up to the subsequent lines, if any
  • On a list style, the top item on the left column has an index of 0. The second item from top on the left column has an index of 1, and so on, up to the subsequent columns, if any
  • On a details style, the most top item has an index of 0. The second item from the top has an index of 1, and so on 

When a list view comes up, it displays its list of items. To use an item, the user can click it. When an item has been clicked, the control fires an OnChanged event, which is of type TLVChangeEvent:

__property TLVChangeEvent OnChange;

Activating an Item

When an item has been selected, it becomes highlighted. If you use the LabelEdit property to allow the user to edit an item, this is a local edition. In the next sections, we will learn how to add sub-items to a list view item. When an item is equipped with sub-items, you may want your application to allow the user to change the item, one of its sub-items, or everything. Before doing anything, an item must be activated. There are three ways an item has been activated.

The technique used to activate an item is supported by the Activation property. The Activation property is based on the ItemActivation enumeration that has three members:

  • Standard: When the Activation property is set to Standard, to activate an item, the user must double-click the item
  • OneClick: With this option, the user would click an item once to active it
  • TwoClick: If you set the Activation property to this member, the user would have to click the item, then click it again to activate it (clicking once and clicking again once is not the same as double-clicking)

When an item has been activated, the control fires an ItemActivate event. You can use either this or the SelectedIndexChanged event to process the item.

Practical LearningPractical Learning: Activating a List View

  1. Double-click an unoccupied are of the form
  2. Implement the event as follows:
    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #include <IOUtils.hpp>
    #pragma hdrstop
    
    #include "PropertiesListing.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TfrmPropertiesListing *frmPropertiesListing;
    //---------------------------------------------------------------------------
    __fastcall TfrmPropertiesListing::TfrmPropertiesListing(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    	. . . No Change
    
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::FormCreate(TObject *Sender)
    {
    	TFileStream * FSProperties = NULL;
    	TFileName FileName = L"C:\\Altair Realtors\\Properties.atr";
    
    	// Check that a folder named Altair Realtors exists.
    	// If it doesn't, create it
    	TDirectory::CreateDirectoryA(L"C:\\Altair Realtors");
    
    	if( TFile::Exists(FileName) )
    	{
    		try {
    			FSProperties = new TFileStream(FileName,
    					fmOpenReadWrite | fmShareDenyWrite );
    			FSProperties->ReadComponent(lvwProperties);
    		}
    		__finally {
    			delete FSProperties;
    		}
    	}
    }
    //---------------------------------------------------------------------------
  3. Save all

The Sub-Items of an Item

 

Introduction

The idea of having columns is to provide more information about each item of a list view instead of a simple string for each. Consider the following example:

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

	TListItem * lviCountry = NULL;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 310;
	lvwCountries->Height = 120;
	lvwCountries->ViewStyle = vsReport;

	TListColumn * colName = lvwCountries->Columns->Add();
	colName->Caption = L"Country Name";
	colName->Width = 90;

	TListColumn * colPopulation = lvwCountries->Columns->Add();
	colPopulation->Caption = "Population";
	colPopulation->Width = 78;
	colPopulation->Alignment = taRightJustify;

	TListColumn * colCapital = lvwCountries->Columns->Add();
	colCapital->Caption = "Capital";
	colCapital->Width = 96;
	colCapital->Alignment = taLeftJustify;

	TListColumn * colCode = lvwCountries->Columns->Add();
	colCode->Caption = "Code";
	colCode->Width = 40;
	colCode->Alignment = taCenter;

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Egypt";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Portugal";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Australia";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Mali";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Sweden";
}
//---------------------------------------------------------------------------

This would produce:

Countries Statistics

Visually Creating Sub Items

To visually create the sub-items, you must use the ListView Item Editor. From that dialog box, click the main item in the left list, then click the New SubItem button.

Practical LearningPractical Learning: Visually Creating Sub Items

  1. On the form, click the list view
  2. In the Object Inspector, click Items and click its ellipsis button
  3. In the ListView Items Editor, as the first item is selected, on the right side, click New SubItem
  4. On the right side, click Caption and type Single Family
  5. Click New SubItem again
  6. On the right side, click Caption and type Silver Spring
  7. Click New SubItem againClick New SubItem again
  8. On the right side, click Caption and type MD
  9. Click Add again
  10. On the right side, click Caption and type 3
  11. Click Add again
  12. On the right side, click Caption and type 1988
     
    ListView Items Editor
  13. Click OK

Programmatically Creating Sub Items

To support sub-items, the TListItem class is equipped with a property called SubItems. This property is of type TStrings:

__property Classes::TStrings * SubItems = {read=FSubItems,write=SetSubItems};

To visually manage the sub-items of an item, you can use the ListView Item Editor. To programmatically manage the sub-items, you can use the properties and methods of the TStrings class, which you should already be familiar with. For example, to create a sub-item, call the Add() method on the SubItems property of a TListItem object. Here are examples:

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

	TListItem * lviCountry = NULL;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 310;
	lvwCountries->Height = 120;
	lvwCountries->ViewStyle = vsReport;

	TListColumn * colName = lvwCountries->Columns->Add();
	colName->Caption = L"Country Name";
	colName->Width = 90;

	TListColumn * colPopulation = lvwCountries->Columns->Add();
	colPopulation->Caption = "Population";
	colPopulation->Width = 78;
	colPopulation->Alignment = taRightJustify;

	TListColumn * colCapital = lvwCountries->Columns->Add();
	colCapital->Caption = "Capital";
	colCapital->Width = 96;
	colCapital->Alignment = taLeftJustify;

	TListColumn * colCode = lvwCountries->Columns->Add();
	colCode->Caption = "Code";
	colCode->Width = 40;
	colCode->Alignment = taCenter;

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Egypt";

	lviCountry->SubItems->Add(L"1,001,450");
	lviCountry->SubItems->Add("Cairo");
	lviCountry->SubItems->Add("eg");

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Portugal";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Australia";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Mali";

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Sweden";
}
//---------------------------------------------------------------------------

This would produce:

Countries Statistics

In the same way, you can add sub-items to some items and ignore some others.

Practical LearningPractical Learning: Creating Sub-Items

  1. Open the form, double-click the New Property button and change its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::btnNewPropertyClick(TObject *Sender)
    {
        int RndNumber1 = Random(9);
        int RndNumber2 = Random(9);
        int RndNumber3 = Random(9);
        int RndNumber4 = Random(9);
        int RndNumber5 = Random(9);
        int RndNumber6 = Random(9);
        int RndNumber7 = Random(9);
        int RndNumber8 = Random(9);
        UnicodeString PropNumber = UnicodeString(RndNumber1) +
    				   UnicodeString(RndNumber2) +
    				   UnicodeString(RndNumber3) +
    				   UnicodeString(RndNumber4) + L"-" +
    				   UnicodeString(RndNumber5) +
    				   UnicodeString(RndNumber6) + L"" +
    				   UnicodeString(RndNumber7) +
    				   UnicodeString(RndNumber8);
        frmPropertyEditor->edtPropertyNumber->Text = PropNumber;
    
        if( frmPropertyEditor->ShowModal() == mrOk )
        {
    	// Check that a folder named Altair Realtors exists.
    	// If it doesn't, create it
    	TDirectory::CreateDirectoryA(L"C:\\Altair Realtors");
    
    	TListItem * lviProperty = lvwProperties->Items->Add();
    
    	lviProperty->Caption = frmPropertyEditor->edtPropertyNumber->Text;
    	lviProperty->SubItems->Add(frmPropertyEditor->cbxPropertyTypes->Text);
    	lviProperty->ImageIndex = frmPropertyEditor->cbxPropertyTypes->ItemIndex;
    	lviProperty->GroupID = frmPropertyEditor->cbxPropertyTypes->ItemIndex;
    	lviProperty->SubItems->Add(frmPropertyEditor->edtCity->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->cbxStates->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->edtStories->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->edtYearBuilt->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->edtBedrooms->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->edtBathrooms->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->cbxConditions->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->cbxStatus->Text);
    	lviProperty->SubItems->Add(frmPropertyEditor->edtMarketValue->Text);
    		
    	if( frmPropertyEditor->PictureFile != L"" )
    	{
    		TFile::Copy(frmPropertyEditor->PictureFile,
    			L"C:\\Altair Realtors\\" +
    			frmPropertyEditor->edtPropertyNumber->Text +
    			TPath::GetExtension(frmPropertyEditor->PictureFile),
    			TRUE);
    	}
    
    	// Reset
    	frmPropertyEditor->edtPropertyNumber->Text = PropNumber;
    	frmPropertyEditor->cbxPropertyTypes->ItemIndex = -1;
    	frmPropertyEditor->edtCity->Text = L"";
    	frmPropertyEditor->cbxStates->ItemIndex = -1;
    	frmPropertyEditor->edtStories->Text = L"";
    	frmPropertyEditor->edtYearBuilt->Text = L"";
    	frmPropertyEditor->edtBedrooms->Text = L"";
    	frmPropertyEditor->edtBathrooms->Text = L"";
    	frmPropertyEditor->cbxConditions->ItemIndex = -1;
    	frmPropertyEditor->cbxStatus->ItemIndex = -1;
    	frmPropertyEditor->edtMarketValue->Text = L"";
    	frmPropertyEditor->imgProperty->Picture = NULL;
    	frmPropertyEditor->PictureFile = L"";
        }
    }
    //---------------------------------------------------------------------------
  2. Return to the form
  3. Click the list view
  4. In the Object Inspector, click Events
  5. Double-click ItemSelectionChanged
  6. Implement the event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::lvwPropertiesSelectItem(TObject *Sender,
    								TListItem *Item,
    								bool Selected)
    {
        TFileName PictureFile;
    
        PictureFile = L"C:\\Altair Realtors\\" + Item->Caption + L".bmp";
    
        if( TFile::Exists(PictureFile) == True )
    	imgProperty->Picture->LoadFromFile(PictureFile);
        else
    	imgProperty->Picture->LoadFromFile(L"C:\\Altair Realtors\\0000-0000.bmp");
    }
    //---------------------------------------------------------------------------
  7. Return to the form
  8. Click an unoccupied area on the form
  9. In the Events section of the Object Inspector, double-click OnClose
  10. Implement its event as follows:
    //---------------------------------------------------------------------------
    void __fastcall TfrmPropertiesListing::FormClose(TObject *Sender,
    						 TCloseAction &Action)
    {
    	TFileStream * FSProperties = NULL;
    	TFileName FileName = L"C:\\Altair Realtors\\Properties.atr";
    
    	try {
    		FSProperties = new TFileStream(FileName, Classes::fmCreate);
    		FSProperties->WriteComponent(lvwProperties);
    	}
    	__finally {
    		delete FSProperties;
    	}
    }
    //---------------------------------------------------------------------------
  11. In the Object Inspector, click the Properties tab

Managing Sub-Items

When you create a new sub-item, it uses a default font and a black color on a white background. If you want, you can change the way a sub-item aesthetically displays. To allow these changes, the list view in the Win32 library provides many functions. To start, you should get a reference to a record (or row) in a list view. For this purpose, the TListItem class is equipped with a property named Handle:

__property HWND__ * Handle = {read=GetHandle};

Deleting Items

To visually delete an item and its sub-items, in the ListView Item Editor, click the item in the left list and click the Delete button. To programmatically delete an item from a list view, you can call the Delete() method of the TCollection. Here is an example that deletes the third item from the list view:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDeleteItemClick(TObject *Sender)
{
	lvwCountries->Items->Delete(2);
}
//---------------------------------------------------------------------------

To delete all items from a list view, you can call the TCollection::Clear() method.

Practical LearningPractical Learning: Deleting Items

  1. On the form, right-click the list view and create Items Editor...
  2. In the Members list, click the first item and click Remove
  3. Click the other item and click Remove
  4. Click OK

Characteristics of a List View

 

Column Header Style

If you create the columns of a list view, when the user displays the detail view, the column headers appear and behave like regular buttons. This also means that the user can click a column header and you can take action. If you don't want this appearance and this behavior, you can make the columns appear flat. This characteristics is controlled by the Boolean ColumnClick property of the TCustomListView class:

__property bool ColumnClick = {read=FColumnClick,write=SetColumnClick};

When this property is set to True, which is its default value, each column header appears in 3-D:

Countries Statistics

If the ColumnClick property is True, when the user clicks a column header, it goes down. If you set the ColumnClick property to False, the column headers appear flat and there is no effect if the user clicks them:

Countries Statistics

Hot Tracking an Item

To select an item in the list, the user can click it. The selected item indicates this by being highlighted. To select another item, the user can click it and this automatically dismisses the previous selection. You can also allow the user to select an item by positioning the mouse over it. This characteristic is controlled by the HotTrack property of the TCustomListView class:

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

When an item has been selected, it is represented by the Selected property of the TCustomListView class:

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

Selecting Multiple Items

If you want, you can give the user the ability to select more than one item or you can prevent the user from selecting more than one item. This characteristic is controlled by the MultiSelect property of the TCustomMultiSelectListControl class:

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

The default value of this property is False, which allows the user to select only one or more items. If you set it to True, the user can select many items at a time.

When many items have been selected, the selected items are stored in a list that starts at the Selected property. This means that the first selected item is the Selected object. To get the second item, call the GetNextItem() method of the TCustomListView class. Its syntax is:

Comctrls::TListItem * __fastcall GetNextItem(Comctrls::TListItem * StartItem,
 					     Comctrls::TSearchDirection Direction,
  					     System::Set<Comctrls::TItemState,0,5> States);

Hiding the Selected State

After selecting an item, if the user clicks another control, the item that was selected would not be highlighted anymore. If you want the control to continue showing the current selection even when the list view loses focus, set the value of the HideSelection Boolean property of the TCustomListView class:

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

Full Row Selection

By default, to select an item, the user must click the item itself and not one of its sub-items. To allow the user to select a an item and its sub-items at the same time, the TCustomListView class provides the FullRowSelect Boolean property:

__property bool RowSelect = {read=FRowSelect,write=SetRowSelect};

Its default value is set to false, which obliges the user to click the item itself. If you set this property to true, the whole row would be highlighted when either you or the user selects it. Here is an example of setting this property:

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

	lvwCountries->RowSelect = True;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Allowing Full Row Selection

  1. On the form, click the list view
  2. In the Object Inspector, click the check box of RowSelect to set its value to True

Grid Lines

When using the report view, to make a list view more indicative, you can show is as a table, made of grid lines. This characteristic is controlled by the GridLines Boolean property of the TCustomListView class:

__property bool GridLines = {read=FGridLines,write=SetGridLines};

The default value of this property is false. If you set it to true, grid lines would appear among items throughout the list view, including empty rows. Here is an example of setting this property:

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

	lvwCountries->GridLines = True;
}
//---------------------------------------------------------------------------

Practical LearningPractical Learning: Showing Grid Lines

  1. In the Object Inspector, double-click GridLines to set its value to True
  2. To execute the application, press F9
  3. Click the New property... button
  4. Create the list of properties as follows (the computer will generate the properties numbers)
     
    Property Type City State Stories Year Built Bedrooms Bathrooms Condition Market Value Status
    Single Family Rockville MD 2 1988 3 2.50 Excellent 465580 Available
    Single Family Silver Spring MD 3 2002 5 3.50 Excellent 675880 Sold
    Townhouse Arlington VA 4 1995 4 3.50 Good 550665 Available
    Condominium Washington DC 8 1984 1 1.00 Good 285775 Available
    Single Family McLean VA 3 1992 5 3.50 Excellent 785680 Available
    Condominium Rockville MD 8 2006 2 1.00 Excellent 316925 Available
    Townhouse Washington DC 2 1975 3 1.50 Good 385600 Sold
    Townhouse Baltimore MD 3 1982 3 1.00 Good 275970 Available

     
    Altair Realtors
     
    Altair Realtors
     
    Altair Realtors 
  5. Close the form and return to your programming environment

List Items and Check Boxes

Besides, or instead of, icons, you can display check boxes with the items of a list view. This characteristic is controlled by the CheckBoxes property:

__property bool Checkboxes = {read=FCheckboxes,write=SetCheckboxes};

The default value of this property is False, which omits displaying the check boxes. If you set it to True, a check box would appear on the left of each item of the list view:

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

	TListColumn * colCountry = NULL;
	TListItem   * lviCountry = NULL;

	lvwCountries->RowSelect = True;
	lvwCountries->GridLines = True;
	lvwCountries->Checkboxes = True;

	lvwCountries->Left = 12;
	lvwCountries->Top  = 12;
	lvwCountries->Width  = 350;
	lvwCountries->Height = 110;
	lvwCountries->ViewStyle = vsReport;

	TListColumn * colName = lvwCountries->Columns->Add();
	colName->Caption = L"Country Name";
	colName->Width = 90;

	colCountry = lvwCountries->Columns->Add();
	colCountry->Caption = L"Area (sq km)";
	colCountry->Width = 75;
	colCountry->Alignment = taRightJustify;

	colCountry = lvwCountries->Columns->Add();
	colCountry->Caption = L"Population";
	colCountry->Width = 70;
	colCountry->Alignment = taRightJustify;

	TListColumn * colCapital = lvwCountries->Columns->Add();
	colCapital->Caption = L"Capital";
	colCapital->Width = 70;
	colCapital->Alignment = taLeftJustify;

	TListColumn * colCode = lvwCountries->Columns->Add();
	colCode->Caption = L"Code";
	colCode->Width = 40;
	colCode->Alignment = taCenter;

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Egypt";

	lviCountry->SubItems->Add(L"1,001,450");
	lviCountry->SubItems->Add(L"80,471,869");
	lviCountry->SubItems->Add(L"Cairo");
	lviCountry->SubItems->Add(L"eg");

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Portugal";

	lviCountry->SubItems->Add("92,391");
	lviCountry->SubItems->Add("10,735,765");
	lviCountry->SubItems->Add("Lisbon");
	lviCountry->SubItems->Add("pt");

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Australia";

	lviCountry->SubItems->Add("7,741,220");
	lviCountry->SubItems->Add("21,515,754");
	lviCountry->SubItems->Add("Canberra");
	lviCountry->SubItems->Add("au");

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Mali";

	lviCountry->SubItems->Add("1,240,192");
	lviCountry->SubItems->Add("13,796,354");
	lviCountry->SubItems->Add("Bamako");
	lviCountry->SubItems->Add("ml");

	lviCountry = lvwCountries->Items->Add();
	lviCountry->Caption = L"Sweden";

	lviCountry->SubItems->Add("450,295");
	lviCountry->SubItems->Add("9,074,055");
	lviCountry->SubItems->Add("Stockholm");
	lviCountry->SubItems->Add("se");
}
//---------------------------------------------------------------------------

This would produce:

Countries Statistics

Alternatively, to display check boxes on the list view, send a LVM_SETEXTENDEDLISTVIEWSTYLE message to the control. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	SendMessage((HWND)lvwCountries->Handle,
		    (UINT)LVM_SETEXTENDEDLISTVIEWSTYLE,
		    (WPARAM)(DWORD) LVS_EX_CHECKBOXES,
		    (LPARAM)LVS_EX_CHECKBOXES);
}
//---------------------------------------------------------------------------
 
 
   
 

Home Copyright © 2010-2011 FunctionX, Inc.