Windows Controls: The List View |
|
Introduction to the List View
Description
A list view is a list of items that presents many options:
Practical Learning: Introducing the List View Control
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AltairRealtors1 { [Serializable] public class RealEstateProperty { public string PropertyNumber { get; set; } public string PropertyType { get; set; } public string City { get; set; } public string State { get; set; } public short Stories { get; set; } public int YearBuilt { get; set; } public short Bedrooms { get; set; } public float Bathrooms { get; set; } public string Condition { get; set; } public string Status { get; set; } public double MarketValue { get; set; } public string PictureFile { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace AltairRealtors1 { public partial class AltairRealtors : Form { List<RealEstateProperty> properties; public AltairRealtors() { InitializeComponent(); } private void AltairRealtors_Load(object sender, EventArgs e) { properties = new List<RealEstateProperty>(); ShowProperties(); } private void ShowProperties() { } } }
List View Creation
The list view control is made available in the .NET Framework through the ListView class that is represented in the Windows Forms section of the Toolbox by the list view button. To add a list view to your application, you can click list view in the Toolbox and click the form or another container.
To programmatically create a list view, you can declare a variable of type ListView, use the new operator to instantiate it and add it to its host's list of controls through a call to the Controls.Add() method. Here is an example:
using System; using System.Drawing; using System.Windows.Forms; public class Exercise : System.Windows.Forms.Form { ListView lvwCountries; public Exercise() { InitializeComponent(); } private void InitializeComponent() { Text = "Countries Statistics"; Size = new Size(452, 218); lvwCountries = new ListView(); lvwCountries.Location = new Point(12, 12); lvwCountries.Width = 420; lvwCountries.Height = 160; Controls.Add(lvwCountries); } } public class Program { static int Main() { System.Windows.Forms.Application.Run(new Exercise()); return 0; } }
After this declaration, an empty rectangular control is created and added to your application. You can then start populating it.
Practical Learning: Creating a List View
|
||||||||||||||||||||||||||||||||||||
Form | ||||||||||||||||||||||||||||||||||||
Text: | Altair Realtors - Properties Listing | |||||||||||||||||||||||||||||||||||
StartPosition: | CenterScreen |
Introduction to the Items of a List View
The Collection of List View Items
The items of a list view are stored in a property called Item, which is of type ListViewItemCollection. The ListViewItemCollection class implements the IList, the ICollection, and the IEnumerable interfaces.
Visually Creating the Items of a List View
To visually create the items of a list view, you can use the ListViewItem Collection Editor of Microsoft Visual Studio. To access it, after adding a list view object to your application:
In both cases, the ListViewItem Collectin Editor would come up:
At design time and in the ListViewItem Collection Editor, to create a new item, you can click the Add button.
Practical Learning: Adding Items to a List View
Programmatically Creating an Item
To help you programmatically create a new item, the ListViewItemCollection class is equipped with the Add() method which is overloaded with three versions. One of the versions of this method uses the following syntax:
public virtual ListViewItem Add(string text);
This method expects a string that will display as the new item. Here is an example:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 160;
lvwCountries.Items.Add("Egypt");
Controls.Add(lvwCountries);
}
This would produce:
As the Items property is in fact a collection, each item is represented by the Item property of the ListViewItemCollection class. This Item property is based on the ListViewItem class. The ListViewItem class is equipped with various constructors, the default of which allows you to instantiate an item without giving much detail.
Instead of directly passing a string to the ListViewItemCollection.Add() method, you can first create a ListViewItem object and pass it to the following version of the ListViewItemCollection.Add() method:
public virtual ListViewItem Add(ListViewItem value);
This method expects a ListViewItem value. One way you can use it consists of providing the string the item would display. To do this, you can use the following constructor of the ListViewItem class:
public ListViewItem(string text);
This constructor expects as argument the text that the new item will display. Here is an example:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 160;
lvwCountries.Items.Add("Egypt");
ListViewItem lviPortugal = new ListViewItem("Portugal");
lvwCountries.Items.Add(lviPortugal);
Controls.Add(lvwCountries);
}
Practical Learning: Creating List View Items
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Form | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FormBorderStyle: | FixedDialog | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Text: | Altair Realtors - Property Editor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
StartPosition: | CenterScreen | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AcceptButton: | btnOK | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CancelButton: | btnCancel | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MaximizeBox: | False | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MinimizeBox: | False | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ShowInTaskBar: | False |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace AltairRealtors1 { public partial class PropertyEditor : Form { public string pictureFile; public PropertyEditor() { InitializeComponent(); } private void PropertyEditor_Load(object sender, EventArgs e) { pictureFile = ""; } private void btnPicture_Click(object sender, EventArgs e) { if (dlgPicture.ShowDialog() == DialogResult.OK) { pbxPicture.Image = Image.FromFile(dlgPicture.FileName); pictureFile = dlgPicture.FileName; } } } }
private void btnNewProperty_Click(object sender, EventArgs e) { PropertyEditor editor = new PropertyEditor(); Random rndNumber = new Random(DateTime.Now.Millisecond); int number1 = rndNumber.Next(100, 999); int number2 = rndNumber.Next(100, 999); string propNumber = number1 + "-" + number2; editor.txtPropertyNumber.Text = propNumber; if( editor.ShowDialog() == DialogResult.OK ) { ListViewItem lviStoreItem = new ListViewItem(editor.txtPropertyNumber.Text); lvwProperties.Items.Add(lviStoreItem); } }
Adding a Range of Items
You can use any of these techniques to create as many items as necessary. Alternatively, if you have many items to create, you can first store them in an array of ListViewItem values, then call the AddRange() method. The syntax of this method is:
public void AddRange(ListViewItem[] items);
This method takes as argument an array of ListViewItem objects. Here is an example:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 160;
lvwCountries.Items.Add("Egypt");
ListViewItem lviPortugal = new ListViewItem("Portugal");
lvwCountries.Items.Add(lviPortugal);
ListViewItem[] lviCountries =
{
new ListViewItem("Australia"),
new ListViewItem("Mali"),
new ListViewItem("Sweden"),
new ListViewItem("Venezuela")
};
lvwCountries.Items.AddRange(lviCountries);
Controls.Add(lvwCountries);
}
Alternatively, you can create an array of strings and pass it to the following constructor of the ListView class:
public ListViewItem(string[] items);
Grouping the Items of a List View
Introduction
To better organize the items of a list view, you can put them in groups. Each group can hold a different set of items and/or a different number of items, but all items must be of the same type.
To support groups, the ListView class is equipped with a property named Groups. This property is based on an enumeration named ListViewGroupCollection:
public ListViewGroupCollection Groups { get; }
ListViewGroupCollection is a classic collection class that implements the IList, the ICollection, and the IEnumerable interfaces, which give it the ability to add and manage groups.
public class ListViewGroupCollection : IList, ICollection, IEnumerable
Creating a Group of Items
To support a group of items, the .NET Framework provides a class named ListViewGroup.
To visually create a group:
Any of these actions would display the ListViewGroup Collection Editor:
To create a group, click Add. In the same way, you can create as many groups as you want. After creating them, click OK.
Characteristics of a Group of Items
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.
Besides a title, a group has a name, which is represented by the Name property.
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 HeaderAlignment property that is of type HorizontalAlignment.
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 ListViewItem Collection Editor. If you had not yet created the items, you must first do that. In the Members list, click an item. In the right list, click Group, then click the arrow of its combo box, and select a group of your choice.
To let you get a list of items that belong to a group, the ListViewGroup class is equipped with a property named Items. This property is of type ListViewItemCollection:
public ListView..::..ListViewItemCollection Items { get; }
To know the list view that a group belongs to, get the value of the ListView property, which is of type ListView:
public ListView ListView { get; }
Practical Learning: Creating a Group of Items
The Styles of a List View
Introduction
A list view provides various options to display its items. To support this, the ListView class is equipped with the View property that is based on the View enumeration. Its members are:
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 views as needed. The different displays of the list view are controlled by the View property of the ListView class. To specify the type of view to use, assign the desired member of the View enumerator to the ListView.View property.
Practical Learning: Using View Styles
|
private void btnLargeIcons_CheckedChanged(object sender, EventArgs e) { lvwProperties.View = View.LargeIcon; }
private void btnSmallIcons_CheckedChanged(object sender, EventArgs e) { lvwProperties.View = View.SmallIcon; }
private void btnList_CheckedChanged(object sender, EventArgs e) { lvwProperties.View = View.List; }
private void btnDetails_CheckedChanged(object sender, EventArgs e) { lvwProperties.View = View.Details; }
private void btnClose_Click(object sender, EventArgs e) { Close(); }
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. In the .NET Framework, these are referred to as large icons.
Before using the pictures, you should store them in image lists. Each set must be stored in its own ImageList object.
To support the various sets of icons, the ListView class is equipped with a property named LargeImageList for the 32x32-pixel icons and another property named SmallImageList for the 16x16-pixel icons. After creating both ImageList 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:
Practical Learning: Associating Icons With Nodes
The Columns of a List View
Introduction
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:
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 ListView class is equipped with the Columns property. The Columns property is an object of type ListView.ColumnHeaderCollection. As its name indicates, the Columns property represents a list of columns. Each column is based on the ColumnHeader class.
At design time, to create the columns:
This would open the ColumnHeader Collection Editor:
To create a column, you can click Add. In the right Properties list, you can click Text and type the string that would display on the column header.
Practical Learning: Visually Creating Columns
Programmatically Creating Columns
To programmatically create a column, you can call the ColumnHeaderCollection.Add() method that is overloaded with two versions. One of the versions of this method uses the following syntax:
public virtual ColumnHeader Add(string caption, int width, HorizontalAlignment textAlign);
The first argument of this method is referred to as the column's caption. It is text that would display in the column header. The second argument is a natural number that represents the distance from the left to the right borders of the column. The last argument specifies how the caption of the column would be aligned. The options are the same as those of the text box: Left, Center, or Right. The default value is Left.
Here is an example of creating a column by calling this method:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 160;
lvwCountries.View = View.Details;
lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left);
Controls.Add(lvwCountries);
}
This would produce:
As mentioned earlier, a column is in fact an object of type ColumnHeader. This class is equipped with all the necessary characteristics that define a column header:
Instead of defining a column in the Add() method, you can first create an object based on the ColumnHeader class and then pass it to the following version of the ColumnHeaderCollection.Add() method:
public virtual int Add(ColumnHeader value);
This method takes as argument a ColumnHeader object. Here is an example:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 100;
lvwCountries.View = View.Details;
lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left);
ColumnHeader colArea = new ColumnHeader();
colArea.Text = "Area";
colArea.Width = 80;
colArea.TextAlign = HorizontalAlignment.Right;
lvwCountries.Columns.Add(colArea);
Controls.Add(lvwCountries);
}
This would produce:
Instead of adding one column at a time as we have done above, you can first create an array of ColumnHeader objects and pass it to the ListView.ColumnHeaderCollection.AddRange() method. Its syntax is:
public virtual void AddRange(ColumnHeader values[]);
Here is an example of using it:
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 214);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 100;
lvwCountries.View = View.Details;
lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left);
ColumnHeader colArea = new ColumnHeader();
colArea.Text = "Area";
colArea.Width = 80;
colArea.TextAlign = HorizontalAlignment.Right;
lvwCountries.Columns.Add(colArea);
ColumnHeader colPopulation = new ColumnHeader();
colPopulation.Text = "Population";
colPopulation.Width = 78;
colPopulation.TextAlign = HorizontalAlignment.Right;
ColumnHeader colCapital = new ColumnHeader();
colCapital.Text = "Capital";
colCapital.Width = 96;
colCapital.TextAlign = HorizontalAlignment.Left;
ColumnHeader colCode = new ColumnHeader();
colCode.Text = "Code";
colCode.Width = 40;
colCode.TextAlign = HorizontalAlignment.Center;
ColumnHeader[] cols = { colPopulation, colCapital, colCode };
lvwCountries.Columns.AddRange(cols);
Controls.Add(lvwCountries);
}
This would produce:
Practical Learning: Creating Columns
(Name) | Text | TextAlign | Width |
colPropertyNumber | Property # | 60 | |
colCity | City | 80 | |
colState | State | Center | 40 |
colStories | Stories | Right | 44 |
colYearBuilt | Year Built | Right | |
colBedrooms | Beds | Right | 40 |
colBathrooms | Baths | Right | 40 |
colCondition | Condition | 70 | |
colStatus | Status | ||
colMarketValue | Value | Right |
Column Insertion
If you call the AddRange() method, its list of columns is created at the end of any existing column, unless there was no other 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 ColumnHeaderCollection.Insert() method. It is overloaded with two versions and their syntaxes are:
public void Insert(int index, ColumnHeader value); public void Insert(int index, string str, int width, HorizontalAlignment textAlign);
In both versions, the first argument specifies the index where the new column will be created inside the Columns collection.
The Number of Columns of a List View
As reviewed above, the columns of a list view are stored in a collection. To know the number of columns of a list view, you can check its ColumnHeaderCollection.Count property.
Locating Columns
To find out if a certain column is part of a list view, you can call the ColumnHeaderCollection.Contains() method. Its syntax is:
public bool Contains(ColumnHeader value);
This method takes as argument a defined ColumnHeader object and scans the list of columns looking for it. If it finds it, it returns true. If it doesn't find a column that matches this object, it returns false. As opposed to looking for a column, you can perform two searches in one by calling the ColumnHeaderCollection.IndexOf() method. Its syntax is:
public int IndexOf(ColumnHeader value);
This method looks for the value ColumnHeader. If it finds it, it returns the column's index from the collection. If the method doesn't find it, it returns -1.
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 ColumnHeader object, you can call the ColumnHeaderCollection.Remove() method. Its syntax is:
public virtual void Remove(ColumnHeader column);
To delete a column based on its position in the collection, you can call the ColumnHeaderCollection.RemoveAt() method. Its syntax is:
public virtual void RemoveAt(int index);
To delete all columns of a list view, you can call the ListView.ColumnHeaderCollection.Clear() method. Its syntax is:
public virtual void Clear();
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:
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 a SelectedIndexChanged event. The SelectedIndexChanged event is of type EventArgs, which means it does not carry any significant information except to let you know that an item has been clicked. Worse, this event does not even let you know the index of the item that was clicked. This means that you must work on your own to identify the item that was clicked.
When the user clicks an item, you can use a technique to identify the item that was selected, when another item gets selected, the the item that was previously selected fires an ItemSelectionChanged event.
Editing a Label
Clicking an item once allows the user to select it. You may create an application that allows the user to edit an item, that is, to change the string that the item displays. To edit an item, the user can click (once) an item, then click (once) the item again. This puts it into edit mode. The user can then use the keyboard to change the string of the item:
To support the ability to let the user edit an item, the ListView class is equipped with the LabelEdit Boolean property. The default value of this property is false, which would prevent the user from editing the item in the list view. If you set this property to true, the user can click, then click the item to edit it.
When the user starts editing, the control fires a BeforeLabelEdit event. This event allows you to take care of some early processing, such as checking what the user is doing or canceling the editing.
If you allow the user to edit the item, after the user has edited it, the control fires an AfterLabelEdit event.
Both the BeforeLabelEdit and the AfterLabelEdit events are of type LabelEditEventArgs. One of the pieces of information that this class provides is the index of the item that is being edited. This index is held by the Item property of the LabelEditEventArgs class. To get the string resulting from the user editing, the LabelEditEventArgs class is equipped with the Label property. When the control fires a BeforeLabelEdit or the a AfterLabelEdit event, to help you decide whether to accept or reject the change, the LabelEditEventArgs class is equipped with the CancelEdit Boolean property.
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:
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.
Using Columns
Besides the items, the user can also use the columns. For example, you can allow the user to re-arrange or sort the list of items with the user clicks a column. When the user a column header, the control fires a ColumnClick event. The ColumnClick event is of type ColumnClickEventArgs. The ColumnClickEventArgs class is equipped with the Column integer property that allows you to identify the index of the column that was clicked.
Besides clicking a column header, the user can also resize a column by dragging the line separator between two columns. If the user decides to resize a column and starts dragging the line separator, the control fires ColumnWidthChanging event. After the user has resized a column, the control fires a ColumnWidthChanged event.
Identifying an Item
The only actual property that the nested ListViewItemCollection class is equipped with is the default Item property. This property allows you to identify an item. There are two versions of the Item property. You can identify an item using its index, which is its zero-based position. As an alternative, you can identify an item using its string.
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:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinForms1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { lvwCountries.View = View.Details; lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left); ColumnHeader colArea = new ColumnHeader(); colArea.Text = "Area"; colArea.Width = 80; colArea.TextAlign = HorizontalAlignment.Right; lvwCountries.Columns.Add(colArea); ColumnHeader colPopulation = new ColumnHeader(); colPopulation.Text = "Population"; colPopulation.Width = 78; colPopulation.TextAlign = HorizontalAlignment.Right; ColumnHeader colCapital = new ColumnHeader(); colCapital.Text = "Capital"; colCapital.Width = 96; colCapital.TextAlign = HorizontalAlignment.Left; ColumnHeader colCode = new ColumnHeader(); colCode.Text = "Code"; colCode.Width = 40; colCode.TextAlign = HorizontalAlignment.Center; ColumnHeader[] cols = { colPopulation, colCapital, colCode }; lvwCountries.Columns.AddRange(cols); lvwCountries.Items.Add("Egypt"); ListViewItem lviPortugal = new ListViewItem("Portugal"); lvwCountries.Items.Add(lviPortugal); ListViewItem lviCountry = new ListViewItem("Australia"); lvwCountries.Items.Add(lviCountry); lviCountry = new ListViewItem("Mali"); lvwCountries.Items.Add(lviCountry); lviCountry = new ListViewItem("Sweden"); lvwCountries.Items.Add(lviCountry); } } }
This would produce:
Visually Creating Sub Items
To visually create the sub-items, you must use the ListViewSubItem Collection Editor. To get it, first access the Properties window of the list view and click the ellipsis button of the Items field. As mentioned previously, this would open the ListView Collection Editor. From that dialog box, you can click the ellipsis button of the SubItems field.
When the ListViewSubItem Collection Editor comes up, to create a sub-item of the current item, you can click Add. Then, on the right side, define the characteristics of the sub-items. You can continue this until you have created all necessary sub-items.
Practical Learning: Visually Creating Sub Items
Programmatically Creating Sub Items
To support sub-items, the ListViewItem class is equipped with a property called SubItems. This property is of type ListViewSubItemCollection. To create a sub-item, you can directly specify its text by passing a string to the ListViewSubItemCollection.Add() method. The ListViewSubItemCollection.Add() method is overloaded with three versions. The version referred to in this case uses the following syntax:
public ListViewSubItem Add(string text);
To identify each piece of information concerning a sub-item, the ListViewSubItemCollection class is equipped with a property called Item, which in turn is based on the ListViewSubItem class. As you can see, the above Add() method returns a ListViewSubItem value.
Here are two examples of calling the above Add() method:
using System; using System.Drawing; using System.Windows.Forms; public class Exercise : Form { ListView lvwCountries; public Exercise() { InitializeComponent(); } private void InitializeComponent() { Text = "Countries Statistics"; Size = new Size(452, 218); lvwCountries = new ListView(); lvwCountries.Location = new Point(12, 12); lvwCountries.Width = 420; lvwCountries.Height = 160; lvwCountries.View = View.Details; lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left); ColumnHeader colArea = new ColumnHeader(); colArea.Text = "Area"; colArea.Width = 80; colArea.TextAlign = HorizontalAlignment.Right; lvwCountries.Columns.Add(colArea); ColumnHeader colPopulation = new ColumnHeader(); colPopulation.Text = "Population"; colPopulation.Width = 78; colPopulation.TextAlign = HorizontalAlignment.Right; ColumnHeader colCapital = new ColumnHeader(); colCapital.Text = "Capital"; colCapital.Width = 96; colCapital.TextAlign = HorizontalAlignment.Left; ColumnHeader colCode = new ColumnHeader(); colCode.Text = "Code"; colCode.Width = 40; colCode.TextAlign = HorizontalAlignment.Center; ColumnHeader[] cols = { colPopulation, colCapital, colCode }; lvwCountries.Columns.AddRange(cols); ListViewItem lviEgypt = lvwCountries.Items.Add("Egypt"); lviEgypt.SubItems.Add("1,001,450"); lviEgypt.SubItems.Add("74,718,797"); lviEgypt.SubItems.Add("Cairo"); lviEgypt.SubItems.Add("eg"); ListViewItem lviPortugal = new ListViewItem("Portugal"); lviPortugal.SubItems.Add("92,391"); lviPortugal.SubItems.Add("10,102,022"); lviPortugal.SubItems.Add("Lisbon"); lviPortugal.SubItems.Add("pt"); lvwCountries.Items.Add(lviPortugal); ListViewItem lviCountry = new ListViewItem("Australia"); lvwCountries.Items.Add(lviCountry); lviCountry = new ListViewItem("Mali"); lvwCountries.Items.Add(lviCountry); lviCountry = new ListViewItem("Sweden"); lvwCountries.Items.Add(lviCountry); StartPosition = FormStartPosition.CenterScreen; Controls.Add(lvwCountries); } } public class Program { static int Main() { System.Windows.Forms.Application.Run(new Exercise()); return 0; } }
This would produce:
As mentioned above, each sub-item is of type ListViewSubItem. The ListViewSubItem class is equipped with three constructors. The default constructor allows you to create an empty sub-item. After declaring a sub-item, you can specify its text by assigning the desired string to the ListViewSubItem.Text property. Instead of directly passing the text of a sub-item to the ListViewSubItemCollection.Add() method as done above, you can first define a ListViewSubItem object using the following constructor of the ListViewSubItem class:
public ListViewSubItem(ListViewItem owner, string text);
The first argument of this constructor specifies the ListViewItem object that this sub-item will belong to. The second argument is simply the string that this sub-item will display. After defining a ListViewSubItem object, you can pass it to the following version of the ListViewSubItemCollection.Add() method:
public ListViewSubItem Add(ListViewItem.ListViewSubItem item);
Here are three examples of using it:
using System;
using System.Drawing;
using System.Windows.Forms;
public class Exercise : System.Windows.Forms.Form
{
ListView lvwCountries;
public Exercise()
{
InitializeComponent();
}
private void InitializeComponent()
{
Text = "Countries Statistics";
Size = new Size(452, 150);
lvwCountries = new ListView();
lvwCountries.Location = new Point(12, 12);
lvwCountries.Width = 420;
lvwCountries.Height = 100;
lvwCountries.View = View.Details;
lvwCountries.Columns.Add("Name", 120, HorizontalAlignment.Left);
ColumnHeader colArea = new ColumnHeader();
colArea.Text = "Area";
colArea.Width = 80;
colArea.TextAlign = HorizontalAlignment.Right;
lvwCountries.Columns.Add(colArea);
ColumnHeader colPopulation = new ColumnHeader();
colPopulation.Text = "Population";
colPopulation.Width = 78;
colPopulation.TextAlign = HorizontalAlignment.Right;
ColumnHeader colCapital = new ColumnHeader();
colCapital.Text = "Capital";
colCapital.Width = 96;
colCapital.TextAlign = HorizontalAlignment.Left;
ColumnHeader colCode = new ColumnHeader();
colCode.Text = "Code";
colCode.Width = 40;
colCode.TextAlign = HorizontalAlignment.Center;
ColumnHeader[] cols = { colPopulation, colCapital, colCode };
lvwCountries.Columns.AddRange(cols);
ListViewItem lviEgypt = lvwCountries.Items.Add("Egypt");
lviEgypt.SubItems.Add("1,001,450");
lviEgypt.SubItems.Add("74,718,797");
lviEgypt.SubItems.Add("Cairo");
lviEgypt.SubItems.Add("eg");
ListViewItem lviPortugal = new ListViewItem("Portugal");
lviPortugal.SubItems.Add("92,391");
lviPortugal.SubItems.Add("10,102,022");
lviPortugal.SubItems.Add("Lisbon");
lviPortugal.SubItems.Add("pt");
lvwCountries.Items.Add(lviPortugal);
ListViewItem lviAustralia = new ListViewItem("Australia");
ListViewItem.ListViewSubItem subAustralia =
new ListViewItem.ListViewSubItem(lviAustralia, "7,686,850");
lviAustralia.SubItems.Add(subAustralia);
subAustralia =
new ListViewItem.ListViewSubItem(lviAustralia, "19,731,984");
lviAustralia.SubItems.Add(subAustralia);
subAustralia =
new ListViewItem.ListViewSubItem(lviAustralia, "Canberra");
lviAustralia.SubItems.Add(subAustralia);
subAustralia = new ListViewItem.ListViewSubItem(lviAustralia, "au");
lviAustralia.SubItems.Add(subAustralia);
lvwCountries.Items.Add(lviAustralia);
ListViewItem lviMali = new ListViewItem("Mali");
ListViewItem.ListViewSubItem subMali =
new ListViewItem.ListViewSubItem(lviMali, "1.24 million");
lviMali.SubItems.Add(subMali);
subMali = new ListViewItem.ListViewSubItem(lviMali, "11,626219");
lviMali.SubItems.Add(subMali);
subMali = new ListViewItem.ListViewSubItem(lviMali, "Bamako");
lviMali.SubItems.Add(subMali);
subMali = new ListViewItem.ListViewSubItem(lviMali, "ml");
lviMali.SubItems.Add(subMali);
lvwCountries.Items.Add(lviMali);
ListViewItem lviSweden = new ListViewItem("Sweden");
ListViewItem.ListViewSubItem subSweden =
new ListViewItem.ListViewSubItem(lviSweden, "449,964");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "8,878,085");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "Stockholm");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "se");
lviSweden.SubItems.Add(subSweden);
lvwCountries.Items.Add(lviSweden);
StartPosition = FormStartPosition.CenterScreen;
Controls.Add(lvwCountries);
}
}
public class Program
{
static int Main()
{
System.Windows.Forms.Application.Run(new Exercise());
return 0;
}
}
This would produce:
If you call the ListViewSubItemCollection.Add() method to create a sub-item, the new sub-item would be added to end of the list. If you want, you can insert the new sub-item somewhere inside the collection. To do this, you would call the ListViewSubItemCollection.Insert() method. Its syntax is:
public void Insert(int index, ListViewItem.ListViewSubItem item);
The first argument is the index that the new sub-item will occupy after being inserted. The second argument is the sub-item to create.
Practical Learning: Creating Sub-Items
private void ShowProperties() { // Get a reference to the file that holds the records of properties string Filename = @"C:\Altair Realtors\properties.atr"; // Make sure the file exists if (File.Exists(Filename) == true) { // if so, create a file stream FileStream stmProperties = new FileStream(Filename, FileMode.Open, FileAccess.Read); // Create a binary formatter BinaryFormatter bfmProperty = new BinaryFormatter(); // If some properties were created already, // get them and store them in the collection properties = (List<RealEstateProperty>)bfmProperty.Deserialize(stmProperties); // First, empty the list view lvwProperties.Items.Clear(); ListViewItem lviProperty = null; // Visit each property in the collection and add it to the list view foreach (RealEstateProperty house in properties) { if (house.PropertyType.Equals("Condominium")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[0]); else if (house.PropertyType.Equals("Townhouse")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[1]); else // if (house.PropertyType.Equals("Single Family")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[2]); lviProperty.SubItems.Add(house.City); lviProperty.SubItems.Add(house.State); lviProperty.SubItems.Add(house.Stories.ToString()); lviProperty.SubItems.Add(house.YearBuilt.ToString()); lviProperty.SubItems.Add(house.Bedrooms.ToString()); lviProperty.SubItems.Add(house.Bathrooms.ToString("F")); lviProperty.SubItems.Add(house.Condition); lviProperty.SubItems.Add(house.Status); lviProperty.SubItems.Add(house.MarketValue.ToString()); lvwProperties.Items.Add(lviProperty); } // Close the file stream stmProperties.Close(); } } private void btnNewProperty_Click(object sender, EventArgs e) { PropertyEditor editor = new PropertyEditor(); Random rndNumber = new Random(DateTime.Now.Millisecond); int number1 = rndNumber.Next(100, 999); int number2 = rndNumber.Next(100, 999); string propNumber = number1 + "-" + number2; editor.txtPropertyNumber.Text = propNumber; // Check that the directory that contains the list of properties exists. // If it doesn't exist, create it DirectoryInfo dirInfo = Directory.CreateDirectory(@"C:\Altair Realtors"); // Get a reference to the file that holds the properties string Filename = @"C:\Altair Realtors\properties.atr"; // First check if the file was previously created if (File.Exists(Filename) == true) { // If the list of properties exists already, // get it and store it in a file stream FileStream stmProperties = new FileStream(Filename, FileMode.Open, FileAccess.Read); BinaryFormatter bfmProperty = new BinaryFormatter(); // Store the list of properties in the collection properties = (List<RealEstateProperty>)bfmProperty.Deserialize(stmProperties); // Close the file stream stmProperties.Close(); } if( editor.ShowDialog() == DialogResult.OK ) { ListViewItem lviStoreItem = new ListViewItem(editor.txtPropertyNumber.Text); RealEstateProperty prop = new RealEstateProperty(); prop.PropertyNumber = editor.txtPropertyNumber.Text; prop.PropertyType = editor.cbxPropertyTypes.Text; prop.City = editor.txtCity.Text; prop.State = editor.cbxStates.Text; prop.Stories = short.Parse(editor.txtStories.Text); prop.YearBuilt = int.Parse(editor.txtYearBuilt.Text); prop.Bedrooms = short.Parse(editor.txtBedrooms.Text); prop.Bathrooms = float.Parse(editor.txtBathrooms.Text); prop.Condition = editor.cbxConditions.Text; prop.Status = editor.cbxStatus.Text; prop.MarketValue = double.Parse(editor.txtMarketValue.Text); if (!editor.pictureFile.Equals("")) { FileInfo flePicture = new FileInfo(editor.pictureFile); flePicture.CopyTo(@"C:\Altair Realtors\" + editor.txtPropertyNumber.Text + flePicture.Extension); prop.PictureFile = @"C:\Altair Realtors\" + editor.txtPropertyNumber.Text + flePicture.Extension; } else prop.PictureFile = @"C:\Altair Realtors\000-000.jpg"; // Add the property in the collection properties.Add(prop); // Get a reference to the properties file string strFilename = dirInfo.FullName + "\\properties.atr"; // Create a file stream to hold the list of properties FileStream stmProperties = new FileStream(strFilename, FileMode.Create, FileAccess.Write); BinaryFormatter bfmProperty = new BinaryFormatter(); // Serialize the list of properties bfmProperty.Serialize(stmProperties, properties); // Close the file stream stmProperties.Close(); // Show the list of properties ShowProperties(); } }
private void lvwProperties_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { RealEstateProperty currentProperty = new RealEstateProperty(); foreach (RealEstateProperty prop in properties) { if( prop.PropertyNumber.Equals(e.Item.SubItems[0].Text) ) pbxPicture.Image = Image.FromFile(prop.PictureFile); } }
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 ListViewItem class is equipped with the UseItemStyleForSubItems Boolean property, whose default value is true. When this property is set to true, the compiler refers to the item that "owns" the current sub-item to paint the sub-item, as we will see in the next section. If you plan to change these aspects, you must first set this property to false.
After setting the ListViewItem.UseItemStyleForSubItems property to false, you can set the following properties of the ListViewSubItem class as you wish:
ListViewItem lviSweden = new ListViewItem("Sweden"); lviSweden.UseItemStyleForSubItems = false; ListViewItem.ListViewSubItem subSweden = new ListViewItem.ListViewSubItem(lviSweden, "449,964"); . . . subSweden = new ListViewItem.ListViewSubItem(lviSweden, "Stockholm"); subSweden.Font = new Font("Times New Roman", 14, FontStyle.Italic); lviSweden.SubItems.Add(subSweden); . . . |
ListViewItem.ListViewSubItem subSweden =
new ListViewItem.ListViewSubItem(lviSweden, "449,964");
subSweden.ForeColor = Color.Red;
lviSweden.SubItems.Add(subSweden);
|
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "8,878,085");
subSweden.BackColor = Color.Blue;
lviSweden.SubItems.Add(subSweden);
|
To restore these settings on the sub-item, you can call the ListViewItem.ListViewSubItem.ResetStyle() method. Its syntax is:
public void ResetStyle();
When called, this method resets the font, the text color, and the background color.
Managing the Items of a List View
The Font, Text Color, and Background of an Item
After adding an item to a list view, the new item assumes some default styles involving the font, the color, and the background. To enhance the appearance of the items, you can change these characteristics that are primarily controlled by the ListViewItem.UseItemStyleForSubItems Boolean property. Its default value is true. You can use it to change the properties of an item as follows:
. . .
ListViewItem lviAustralia = new ListViewItem("Australia");
lviAustralia.Font = new Font("Georgia", 8, FontStyle.Bold);
ListViewItem.ListViewSubItem subAustralia =
new ListViewItem.ListViewSubItem(lviAustralia, "7,686,850");
lviAustralia.SubItems.Add(subAustralia);
subAustralia = new ListViewItem.ListViewSubItem(lviAustralia,
"19,731,984");
lviAustralia.SubItems.Add(subAustralia);
subAustralia = new ListViewItem.ListViewSubItem(lviAustralia,
"Canberra");
lviAustralia.SubItems.Add(subAustralia);
subAustralia = new ListViewItem.ListViewSubItem(lviAustralia, "au");
lviAustralia.SubItems.Add(subAustralia);
lvwCountries.Items.Add(lviAustralia);
. . .
|
ListViewItem lviSweden = new ListViewItem("Sweden");
lviSweden.ForeColor = Color.Red;
ListViewItem.ListViewSubItem subSweden =
new ListViewItem.ListViewSubItem(lviSweden, "449,964");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "8,878,085");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "Stockholm");
lviSweden.SubItems.Add(subSweden);
subSweden = new ListViewItem.ListViewSubItem(lviSweden, "se");
lviSweden.SubItems.Add(subSweden);
lvwCountries.Items.Add(lviSweden);
|
ListViewItem lviEgypt = lvwCountries.Items.Add("Egypt");
lviEgypt.BackColor = Color.Blue;
lviEgypt.SubItems.Add("1,001,450");
lviEgypt.SubItems.Add("74,718,797");
lviEgypt.SubItems.Add("Cairo");
lviEgypt.SubItems.Add("eg");
|
Locating a List View Item
The items of a list view are stores in a collection represented by the ListView.Items property. To know the number of items in the list, you can retrieve the value of the ListViewItemCollection.Count property. Each member of this collection has an index represented by the ListViewItemCollection.Index property.
You can also locate an item using the coordinates of a point inside its bounding area. To use this technique, you can call the GetItemAt() method of the ListView class. Its syntax is:
public ListViewItem GetItemAt(int x, int y);
This method expects the coordinates (x, y) of a point. If an item is found at that point, this method returns it. If there is no item at that point, the method returns 0.
Deleting Items
To delete an item from a list view, you can call the ListViewItemCollection.Remove() method. Its syntax is:
public virtual void Remove(ListViewItem item);
This method takes as argument the ListViewItem object to be deleted. If you are already positioned at that item, you can call its own ListViewItem.Remove() method. Its syntax is:
public virtual void Remove();
To delete an item based on its index, you can call the ListViewItemCollection.RemoveAt() method whose syntax is:
public virtual void RemoveAt(int index);
When calling this method, you must pass the index of the undesired item. If the item is found, it would be deleted. If you provide a negative index or one that is higher than the ListViewItemCollection.Count property, the compiler would throw an ArgumentOutOfRangeException exception.
To delete all items from a list view, you can call the ListViewItem.Clear() method. Its syntax is:
public virtual void Clear();
When called, this method removes all items of the list view.
Practical Learning: Deleting Items
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 HeaderStyle property of the ListView class. This property is based on the ColumnHeaderStyle enumerator. Its members are:
lvwCountries.HeaderStyle = ColumnHeaderStyle.Clickable;
|
lvwCountries.HeaderStyle = ColumnHeaderStyle.Nonclickable; |
lvwCountries.HeaderStyle = ColumnHeaderStyle.None; |
Selecting Items in a List View
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. 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 ListView class. Its default value is true, which allows the user to select one or more items. If you set it to false, the user can select only one item at a time.
You can also allow the user to select an item by positioning the mouse over it. This characteristic is controlled by the HoverSelection property of the ListView class.
When an item has been selected or more than one item are selected, the selected items are stored in a list represented by the SelectedItems property of the ListView class. The ListView.SelectedItems property is an object based on the ListView.SelectedListViewItemCollection class. If the ListView.MultiSelect property is set to false, this collection would contain only one item.
The number of items selected in the control is known as the Count property of the SelectedListViewItemCollection class. Each item selected can be identified through the Item indexed property of the SelectedListViewItemCollection class.
The SelectedListViewItemCollection class holds a list of the objects that are selected and each is identified as a ListViewItem. If you are more interested in the positions of the items selected and not necessarily their objects, you can use the SelectedIndices property of the ListView class. Each item selected has its index stored in this list. The ListView.SelectedIndices property is based on the ListView.SelectedIndexCollection class.
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 ListView class accordingly.
Full Row Selection
By default, to select an item, the user must click the item itself and not one of its sub-items. If you want an item and its sub-items to be selected when the user clicks anything on their line, you can change the value of the ListView.FullRowSelect Boolean property. 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.
Practical Learning: Allowing Full Row Selection
Grid Lines
When using the detail view, to make a list view more indicative, you can underline each row. This characteristic is controlled by the GridLines Boolean property of the ListView class. The default value of this property is false. If you set it to true, horizontal grid lines would appear among items throughout the list view, including empty rows:
lvwCountries.GridLines = true; |
Practical Learning: Writing Code For a Toolbar
Property Type | City | State | Stories | Year Built | Bedrooms | Bathrooms | Condition | Market Value | Status |
Single Family | Rockville | MD | 2 | 1988 | 3 | 2.5 | Excellent | 465580 | Available |
Single Family | Silver Spring | MD | 3 | 2002 | 5 | 3.5 | Excellent | 675880 | Sold |
Townhouse | Arlington | VA | 4 | 1995 | 4 | 3.5 | Good | 550665 | Available |
Condominium | Washington | DC | 6 | 1984 | 1 | 1 | Good | 285775 | Available |
Single Family | McLean | VA | 3 | 1992 | 5 | 3.5 | Excellent | 785680 | Available |
Condominium | Rockville | MD | 8 | 2006 | 2 | 1 | Excellent | 316925 | Available |
Townhouse | Washington | DC | 2 | 1975 | 3 | 1.5 | Good | 385600 | Sold |
Townhouse | Baltimore | MD | 3 | 1982 | 3 | 1 | Good | 275970 | Available |
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. Its default value 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:
lvwCountries.CheckBoxes = true;
|
||
Home | Copyright © 2010-2020, FunctionX | |
|