ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Working with ListView

by Budi Kurniawan co-author of VB.NET Core Classes in a Nutshell
10/28/2002

Anyone using the Windows operating system must be familiar with the Windows Explorer program, the built-in application used for browsing the file system. Depending on which version your Windows is, the Windows Explorer has four or five views. The four main views are List, Details, SmallIcon and LargeIcon. Windows Explorer is mentioned here because the easiest way to start learning about ListView is to take a close look at your Windows Explorer, especially the four available views. In this article, we first discuss the System.Windows.Forms.ListView and System.Windows.Forms.ListViewItem classes and present two examples of ListView in Details and LargeIcon views. Later, we write a small program that collects the files and directories in the current directory and displays it in a ListView control.

Related Reading

VB.NET Core Classes in a Nutshell
By Budi Kurniawan, Ted Neward

The ListView Class

The ListView class resides in the System.Windows.Forms namespace. It is a Windows control and is derived from the System.Windows.Forms.Control class. It has only one constructor, which is a no-argument constructor. You can add a ListView control to a Windows form just like you would other controls. Here is how you add a ListView control called listView to a form:


ListView listView = new ListView();
this.Controls.Add(listView);

The view of a ListView control is determined by the value of its View property. This property can take one of the members of the System.Windows.Forms.View enumeration, which are as follows: List. Each item appears as a small icon with a label to its right. Items are arranged in columns with no column headers. This is the simplest view of all. Details. Each item appears on a separate line with further information about each item arranged in columns. The leftmost column contains a small icon and label, and subsequent columns contain subitems as specified by the application. A column displays a header, which can display a caption for the column. SmallIcon. Each item appears as a small icon with a label to its right. LargeIcon. Each item appears as a full-sized icon with a label below it.

The default value for the View property is View.LargeIcon. The LargeImageList property is assigned an ImageList object containing a collection of images that will be displayed with each item in the LargeIcon view. The SmallImageList property is similar to the LargeImageList, but its images are used for the SmallIcon view.

For these two properties to work, you must assign an item's ImageIndex property with an index position of the image in the SmallImageList or LargeImageList properties. Another important property, CheckBoxes, takes a boolean indicating whether or not a check box appears next to the ListView control. By default, the value of this property is false. If it is set to true, you can use the CheckedIndices property to obtain the indices of the checked items. Alternatively, the CheckedItems property is provided to get all of the checked items.

If the CheckBoxes property is set to true, you can replace the check boxes with your own images. You should add two images to an ImageList object, and then assign this ImageList object to the StateImageList property of your ListView control. The image at index position 0 is displayed as an unchecked item and the image at index position 1 as a checked item.

For the Details view, you can add columns with headers using the Add method of the ListView's ColumnHeaderCollection, represented by the Columns property. For example, the following adds four columns to the ListView control called listView:


    listView.Columns.Add("Name", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Size", 
                         -2, 
                         HorizontalAlignment.Right);
    listView.Columns.Add("Type", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Modified", 
                         -2, 
                         HorizontalAlignment.Left);
There are two overloads of the Add method, as follows:

public virtual int Add( ColumnHeader value );
public virtual ColumnHeader Add( 
  string str, 
  int width, 
  HorizontalAlignment textAlign
);

In the second overload, width is the initial width of the column header. If you assign -1 to this argument, the column header will be sized automatically to the largest sub-item text in the column. Assign -2, and the column header will be sized to the text size of the column header.

The textAlign argument in the second overload can have one of the members of the System.Windows.Forms.HorizontalAlignment enumeration: Center, Left, or Right. Each item is added to the ListView control using the Add or AddRange method of the ListView's Items collection.

The ListViewItem Class

The ListViewItem class represents an item in a ListView control. This class has several constructors that allow you to pass no argument, the text for the item, subitems, and image index. If you construct a ListViewItem object without passing the needed subitems, you can at a later stage add subitems using the Add method of the ListViewItem.ListViewSubItemCollection class. The ListViewSubItemCollection of a ListViewItem object is represented by the SubItems property. For example, the following code adds a number of subitems to a ListViewItem object.


    ListViewItem item = new ListViewItem("Item 1");
    item.SubItems.Add("SubItem 1");
    item.SubItems.Add("SubItem 2");

Using the Details View

The following example presents a ListView control used to display a collection of three items. Each item represents an author and has two subitems (the title and the book price). The code is given in Listing 1 and the result is depicted in Figure 1.

Listing 1: A ListView in the Details view


using System;
using System.Windows.Forms;
using System.Drawing;

public class ListView1 : Form {
  ListView listView = new ListView();

  public ListView1() {
    listView.Dock = DockStyle.Fill;
    PopulateListView();
    this.Controls.Add(listView);
    this.ClientSize = new Size(400, 200);
  }


  private void PopulateListView() {
    // Set the view to show details.
    listView.View = View.Details;
 
    // Add columns
    listView.Columns.Add("Author", 
                         -2, 
                         HorizontalAlignment.Center);
    listView.Columns.Add("Title", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Price", 
                         -2, 
                         HorizontalAlignment.Left);

    // Add items
    ListViewItem item1 = new ListViewItem("Steve Martin");
    item1.SubItems.Add("Programming .NET");
    item1.SubItems.Add("39.95");

    ListViewItem item2 = new ListViewItem("Irene Suzuki");
    item2.SubItems.Add("VB.NET Core Studies");
    item2.SubItems.Add("69.95");

    ListViewItem item3 = new ListViewItem("Ricky Ericsson");
    item3.SubItems.Add("Passing Your .NET Exams");
    item3.SubItems.Add("19.95");

    // Add the items to the ListView.
    listView.Items.AddRange(
                            new ListViewItem[] {item1, 
                                                item2, 
                                                item3}
                            );
  }

  public static void Main() {
    ListView1 form = new ListView1();
    Application.Run(form);
  }
}
Figure 1
Figure 1: The Details view of the ListView control

Using the LargeIcon View

Another view of the ListView control is LargeIcon. To use this view, you must set the View property of the ListView to View.LargeIcon. You must also construct an ImageList control and add one or more images to the ImageList control. In the code in Listing 2, an image (C:\temp\MyImage.bmp) is added to the ImageList imageList, which is then assigned to the LargeImageList of the ListView control.

Listing 2: Using the LargeIcon view


using System;
using System.Windows.Forms;
using System.Drawing;

public class ListView2 : Form {

  ListView listView = new ListView();

  public ListView2() {
    listView.Dock = DockStyle.Fill;
    PopulateListView();
    this.Controls.Add(listView);
    this.ClientSize = new Size(400, 200);
  }

  private void PopulateListView() {
    // Set the view to show details.
    listView.View = View.LargeIcon;
    ImageList imageList = new ImageList();
    imageList.Images.Add(
                       Bitmap.FromFile(@"C:\temp\MyImage.bmp")
                        );
     
    listView.LargeImageList = imageList;
 
    // Add columns, with listView.VIew = View.LargeIcon, 
    // the following 3 lines have no effect
    listView.Columns.Add("Author", 
                         -2, 
                         HorizontalAlignment.Center);
    listView.Columns.Add("Title", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Price", 
                         -2, 
                         HorizontalAlignment.Left);


    ListViewItem item1 = new ListViewItem("Steve Martin");
    item1.SubItems.Add("Programming .NET");
    item1.SubItems.Add("39.95");
    item1.ImageIndex = 0;

    ListViewItem item2 = new ListViewItem("Irene Suzuki");
    item2.SubItems.Add("VB.NET Core Studies");
    item2.SubItems.Add("69.95");
    item2.ImageIndex = 0;

    ListViewItem item3 = new ListViewItem("Ricky Ericsson");
    item3.SubItems.Add("Passing Your .NET Exams");
    item3.SubItems.Add("19.95");
    item3.ImageIndex = 0;

    // Add the items to the ListView.
    listView.Items.AddRange(
                            new ListViewItem[] {item1, 
                                                item2, 
                                                item3}
                            );
  }


  public static void Main() {
    ListView2 form = new ListView2();
    Application.Run(form);
  }
}

After compilation, you can run the ListView2 class. It will give you the result like the one shown in Figure 2.

Figure 2
Figure 2: A ListView control with the LargeIcon view

Displaying A Directory's Contents Using ListView

As the last example, consider the code in Listing 3. It grabs the content of the current directory (the directory from which the .exe file is run) and displays the subdirectories and files in that directory. An ImageList called imageList is constructed and two images are added to it. Both images reside in the images directory of the application directory. The first one (File.gif) is added to each file item, and the second one (Folder.gif) is used for each folder item.

Listing 3: Using ListView to display a directory's contents


using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.Text;

public class ListView3 : Form {

  ListView listView = new ListView();

  public ListView3() {
    listView.Dock = DockStyle.Fill;
    PopulateListView();
    this.Controls.Add(listView);
    this.ClientSize = new Size(400, 200);
    listView.SelectedIndexChanged += 
                new EventHandler(listView_SelectedIndexChanged);
  }

  private void listView_SelectedIndexChanged(Object sender, 
                                            EventArgs e) {
    ListView.SelectedListViewItemCollection 
                        selectedItems = listView.SelectedItems;
    
    StringBuilder sb = new StringBuilder(1024);
    sb.Append("You selected the following item(s).\n");
    
    int count = selectedItems.Count;
    for (int i=0; i<count; i++) {
      sb.Append("\t").Append(selectedItems[i].Text)
                               .Append("\n");
    }
    MessageBox.Show(sb.ToString());
  }
  
  private void PopulateListView() {
    // Set the view to show details.
    listView.View = View.Details;
    ImageList imageList = new ImageList();
    try {
      imageList.Images.Add(
                        Bitmap.FromFile("./images/File.gif")
                          );
      imageList.Images.Add(
                        Bitmap.FromFile("./images/Folder.gif")
                          );
    }
    catch (FileNotFoundException) {}

    listView.SmallImageList = imageList;
 
    //Add columns, 
    listView.Columns.Add("Name", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Size", 
                         -2, 
                         HorizontalAlignment.Right);
    listView.Columns.Add("Type", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Modified", 
                         -2, 
                         HorizontalAlignment.Left);

    String currentDirectory = Directory.GetCurrentDirectory();
    this.Text = currentDirectory;
    ListViewItem item;

    String[] directories = 
                   Directory.GetDirectories(currentDirectory);
    int length = directories.Length;
    for (int i=0; ilength; i++) {
      item = new ListViewItem(Path.GetFileName(directories[i]),
                              1);
      item.SubItems.Add("");
      item.SubItems.Add("File Folder");
      item.SubItems.Add(
          Directory.GetLastAccessTime(directories[i]).ToString()
                       );
      listView.Items.Add(item);
    }

    String[] files = Directory.GetFiles(currentDirectory);
    length = files.Length;
    for (int i=0; i<length; i++) {
      item = new ListViewItem(Path.GetFileName(files[i]), 0);
      //get file length
      FileInfo fi = new FileInfo(files[i]);
      item.SubItems.Add(Convert.ToString(fi.Length));
      item.SubItems.Add("Document");
      item.SubItems.Add(
                      File.GetLastWriteTime(files[i]).ToString()
                       );
      listView.Items.Add(item);
    }
  }
  public static void Main() {
    ListView3 form = new ListView3();
    Application.Run(form);
  }
}
The majority of the work is done in the PopulateListView method. First, it sets the View property of the ListView with View.Details:

    listView.View = View.Details;

Then, it constructs an ImageList object and adds two images to it:


    ImageList imageList = new ImageList();
    try {
      imageList.Images.Add(
                Bitmap.FromFile("./images/File.gif")
                          );
      imageList.Images.Add(
                Bitmap.FromFile("./images/Folder.gif")
                          );
    }
    catch (FileNotFoundException) {}

The ImageList object is then assigned to the SmallImageList property of the ListView so that each item will have an image.


    listView.SmallImageList = imageList;

Next, it adds four columns: Name, Size, Type, and Modified.


    //Add columns, 
    listView.Columns.Add("Name", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Size", 
                         -2, 
                         HorizontalAlignment.Right);
    listView.Columns.Add("Type", 
                         -2, 
                         HorizontalAlignment.Left);
    listView.Columns.Add("Modified", 
                         -2, 
                         HorizontalAlignment.Left);

Up to this point, we're done with the ListView object. Obtaining the current directory's content starts by invoking the static GetCurrentDirectory method of the System.IO.Directory class. This method returns a string containing the path to the current directory.


    String currentDirectory = Directory.GetCurrentDirectory();

This is then assigned to the form's Text property so that the current directory is displayed as the form's title.


    this.Text = currentDirectory;

The list of subdirectories can be obtained from the GetDirectories static method of the Directory class, passing the path to the directory. Once the list of directories is returned as an array of strings, we iterate each item in the collection, constructing a ListViewItem object and adding it to the ListView control.


    String[] directories = 
                     Directory.GetDirectories(currentDirectory);
    int length = directories.Length;
    for (int i=0; i<length; i++) {
      item = new ListViewItem(Path.GetFileName(directories[i]), 
                              1);
      item.SubItems.Add("");
      item.SubItems.Add("File Folder");
      item.SubItems.Add(
        Directory.GetLastAccessTime(directories[i]).ToString()
                       );
      listView.Items.Add(item);
    }

Next, we do the same with the list of files, obtained from the GetFiles static method of the System.IO.Directory class.


    String[] files = Directory.GetFiles(currentDirectory);
    length = files.Length;
    for (int i=0; i<length; i++) {
      item = new ListViewItem(Path.GetFileName(files[i]), 0);
      //get file length
      FileInfo fi = new FileInfo(files[i]);
      item.SubItems.Add(Convert.ToString(fi.Length));
      item.SubItems.Add("Document");
      item.SubItems.Add(
                      File.GetLastWriteTime(files[i]).ToString()
                       );
      listView.Items.Add(item);
    }
  }

We also capture the ListView control's SelectedIndexChanged event and wires the event with the listView_SelectedIndexChanged event handler.


listView.SelectedIndexChanged += 
                new EventHandler(listView_SelectedIndexChanged);

Every time the user selects a new item or multiple items, the SelectedIndexChanged event will be triggered. What the event handler of this event (listView_SelectedIndexChanged) does is get the ListView.SelectedListViewItemCollection from the SelectedItems property.


    ListView.SelectedListViewItemCollection selectedItems = 
                                         listView.SelectedItems;

Then, it iterates the collection to build a StringBuilder, iterating each of the items.


    StringBuilder sb = new StringBuilder(1024);
    sb.Append("You selected the following item(s).\n");
    
    int count = selectedItems.Count;
    for (int i=0; i<count; i++) {
      sb.Append("\t").Append(selectedItems[i].Text)
                               .Append("\n");
    }
    MessageBox.Show(sb.ToString());
  }

A screenshot of the run application is given in Figure 3.

Figure 3
Figure 3: Displaying the current directory's content

The complete application for this example can be downloaded here

Budi Kurniawan is a senior J2EE architect and author.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.