The ListView Control


Figure 14-19 below shows probably the most commonly known ListView in Windows; the list from which you select files to open in the standard dialog boxes in Windows is a ListView control. Everything you can do to the view in the standard list view dialog (Large icons, details view, and so on), you can do with the ListView control provided with the .NET Framework.

image from book
Figure 14-19

The list view is usually used to present data where the user is allowed some control over the detail and style of the presentation. It is possible to display the data contained in the control as columns and rows much like in a grid, as a single column or with varying icon representations. The most commonly used list view is like the one seen earlier, which is used to navigate the folders on a computer.

The ListView control is easily the most complex control you encounter in this chapter, and covering all of it is beyond the scope of this book. What this chapter does is provide a solid base for you to work on by writing an example that utilizes many of the most important features of the ListView control, and by a thorough description of the numerous properties, events, and methods that can be used. You also look at the ImageList control, which is used to store the images used in a ListView control.

ListView Properties

Name

Description

Activation

By using this property, you can control how a user activates an item in the list view.

The possible values are:

Standard: This setting is that which the user has chosen for his or her machine.

OneClick: Clicking an item activates it.

TwoClick: Double-clicking an item activates it.

Alignment

This property allows you to control how the items in the list view are aligned. The four possible values are:

Default: If the user drags and drops an item it remains where he or she dropped it.

Left: Items are aligned to the left edge of the ListView control.

Top: Items are aligned to the top edge of the ListView control.

SnapToGrid: The ListView control contains an invisible grid to which the items will snap.

AllowColumnReorder

If you set this property to true, you allow the user to change the order of the columns in a list view. If you do so, you should be sure that the routines that fill the list view are able to insert the items properly, even after the order of the columns is changed.

AutoArrange

If you set this property to true, items will automatically arrange themselves according to the Alignment property. If the user drags an item to the center of the list view, and Alignment is Left, then the item will automatically jump to the left of the list view. This property is only meaningful if the View property is LargeIcon or SmallIcon.

CheckBoxes

If you set this property to true, every item in the list view will have a CheckBox displayed to the left of it. This property is only meaningful if the View property is Details or List.

CheckedIndices CheckedItems

These two properties give you access to a collection of indices and items, respectively, containing the checked items in the list.

Columns

A list view can contain columns. This property gives you access to the collection of columns through which you can add or remove columns.

FocusedItem

This property holds the item that has focus in the list view. If nothing is selected, it is null.

FullRowSelect

When this property is true, and an item is clicked, the entire row in which the item resides will be highlighted. If it is false, only the item itself will be highlighted.

GridLines

Setting this property to true causes the list view to draw grid lines between rows and columns. This property is only meaningful when the View property is Details.

HeaderStyle

You can control how the column headers are displayed. There are three styles:

Clickable: The column header works like a button.

NonClickable: The column headers do not respond to mouse clicks.

None: The column headers are not displayed.

HoverSelection

When this property is true, the user can select an item in the list view by hovering the mouse pointer over it.

Items

The collection of items in the list view.

LabelEdit

When this property is true, the user can edit the content of the first column in a Details view.

LabelWrap

If this property is true, labels will wrap over as many lines as needed to display all of the text.

LargeImageList

This property holds the ImageList, which holds large images. These images can be used when the View property is LargeIcon.

MultiSelect

Set this property to true to allow the user to select multiple items.

Scrollable

Set this property to true to display scrollbars.

SelectedIndices SelectedItems

These two properties contain the collections that hold the indices and items that are selected, respectively.

SmallImageList

When the View property is SmallIcon this property holds the ImageList that contain the images used.

Sorting

You can allow the list view to sort the items it contains. There are three possible modes:
Ascending
Descending
None

StateImageList

The ImageList contains masks for images that are used as overlays on the LargeImageList and SmallImageList images to represent custom states.

TopItem

Returns the item at the top of the list view.

View

A list view can display its items in four different modes:

LargeIcon: All items are displayed with a large icon (32 32) and a label.

SmallIcon: All items are displayed with a small icon (16 16) and a label.

List: Only one column is displayed. That column can contain an icon and a label.

Details: Any number of columns can be displayed. Only the first column can contain an icon.

Tile (only available on Windows XP and newer Windows platforms): Displays a large icon with a label and subitem information to the right of the icon.

ListView Methods

For a control as complex as the list view, there are surprisingly few methods specific to it. They are described in the following table.

Name

Description

BeginUpdate()

By calling this method you tell the list view to stop drawing updates until EndUpdate() is called. This is useful when you are inserting many items at once, because it stops the view from flickering and dramatically increases speed.

Clear()

Clears the list view completely. All items and columns are removed.

EndUpdate()

Call this method after calling BeginUpdate. When you call this method, the list view will draw all of its items.

EnsureVisible()

When you call this method, the list view will scroll itself to make the item with the index you specified visible.

GetItemAt()

Returns the ListViewItem at position x,y in the list view.

ListView Events

The ListView control events that you might want to handle are listed in the following table.

Name

Description

AfterLabelEdit

This event occurs after a label has been edited.

BeforeLabelEdit

This event occurs before a user begins editing a label.

ColumnClick

This event occurs when a column is clicked.

ItemActivate

This event occurs when an item is activated.

ListViewItem

An item in a list view is always an instance of the ListViewItem class. the ListViewItem holds information such as text and the index of the icon to display. ListViewItem objects have a SubItems property that holds instances of another class, ListViewSubItem. These subitems are displayed if the ListView control is in Details or tile mode. Each of the subitems represents a column in the list view. The main difference of the subitems and the main items is that a subitem cannot display an icon.

You add ListViewItems to the ListView through the Items collection, and ListViewSubItems to a ListViewItem through the SubItems collection on the ListViewItem.

ColumnHeader

To make a list view display column headers you add instances of a class called ColumnHeader to the Columns collection of the ListView. ColumnHeaders provide a caption for the columns that can be displayed when the ListView is in Details mode.

The ImageList Control

The ImageList control provides a collection that can be used to store images used in other controls on your form. You can store images of any size in an image list, but within each control every image must be of the same size. In the case of the ListView, this means that you need two ImageList controls to be able to display both large and small images.

The ImageList is the first control you visit in this chapter that does not display itself at runtime. When you drag it to a form you are developing, it is not placed on the form itself, but below it in a tray, which contains all such components. This nice feature is provided to stop controls that are not part of the user interface from clogging up the form designer. The control is manipulated in exactly the same way as any other control, except that you cannot move it around.

You can add images to the ImageList at both design time and runtime. If you know at design time what images you want to display, you can add the images by clicking the button at the right side of the Images property. This will bring up a dialog in which you can browse to the images you wish to insert. If you choose to add the images at runtime, you add them through the Images collection.

The best way of learning about using a ListView control and its associated image lists is through an example. In the following Try It Out, you create a dialog with a ListView and two ImageLists. the ListView will display files and folders on your hard drive. For the sake of simplicity, you will not extract the correct icons from the files and folders, but rather will use a standard folder icon for the folders and an information icon for files.

By double-clicking the folders you can browse into the folder tree and a Back button is provided to move up the tree. Five radio buttons are used to change the mode of the list view at runtime. If a file is double- clicked you'll attempt to execute it.

Try It Out – ListView Example

image from book

As always, you start by creating the user interface:

  1. Create a new Windows application called ListView in the C:\BegVCSharp\Chapter14 directory.

  2. Add a ListView, a Button, a Label, and a GroupBox to the form. Then, add five radio buttons to the group box to get a form that looks like Figure 14-20. To set the width of the Label control you have to set its AutoSize property to False.

    image from book
    Figure 14-20

  3. Name the controls as shown in Figure 14-20. The ListView will not display its name as in the picture above; I've added an extra item just to show the name here — you don't need to add this item.

  4. Change the Text properties of the radio buttons and button to be the same as the name, except for the control names, and set the Text property of the form to ListView.

  5. Clear the Text property of the label.

  6. Add two ImageList controls to the form by double-clicking this control's icon in the Toolbox. You can find the ImageList control on the All Windows Forms tab in the Toolbox. Rename the controls imageListSmall and imageListLarge.

  7. Change the Size property of the ImageList named imageListLarge to 32, 32.

  8. Click the button to the right of the Images property of the imageListLarge image list to bring up the dialog on which you can browse to the images you want to insert.

  9. Click Add and browse to the folder ListView in the code for this chapter. The files are:

    Folder 32x32.ico and Text 32x32.ico

  10. Make sure that the folder icon is at the top of the list.

  11. Repeat steps 8 and 9 with the other ImageList, imageListSmall, choosing the 16x16 versions of the icons.

  12. Set the Checked property of the radio button radioButtonDetails to true.

  13. Set the properties shown in the following table on the list view.

    Property

    Value

    LargeImageList

    imageListLarge

    SmallImageList

    imageListSmall

    View

    Details

Adding the Event Handlers

That concludes the user interface, and you can move on to the code. First of all, you need a field to hold the folders you browsed through in order to be able to return to them when the Back button is clicked. You will store the absolute path of the folders, so choose a StringCollection for the job:

partial class Form1 : Form { // Member field to hold previous folders private System.Collections.Specialized.StringCollection folderCol; 

You didn't create any column headers in the forms designer, so you have to do that now. You create them in a method called CreateHeadersAndFillListView():

 private void CreateHeadersAndFillListView() { ColumnHeader colHead; // First header colHead = new ColumnHeader(); colHead.Text = "Filename"; this.listViewFilesAndFolders.Columns.Add(colHead); // Insert the header // Second header colHead = new ColumnHeader(); colHead.Text = "Size"; this.listViewFilesAndFolders.Columns.Add(colHead); // Insert the header // Third header colHead = new ColumnHeader(); colHead.Text = "Last accessed"; this.listViewFilesAndFolders.Columns.Add(colHead); // Insert the header } 

You start by declaring a single variable, colHead, which is used to create the three column headers. For each of the three headers, you declare the variable as new and assign the Text to it before adding it to the Columns collection of the ListView.

The final initialization of the form as it is displayed the first time is to fill the list view with files and folders from your hard disk. This is done in another method:

 private void PaintListView(string root) { try { // Two local variables that are used to create the items to insert ListViewItem lvi; ListViewItem.ListViewSubItem lvsi; // If there's no root folder, we can't insert anything. if (root.CompareTo("") == 0) return; // Get information about the root folder. DirectoryInfo dir = new DirectoryInfo(root); // Retrieve the files and folders from the root folder. DirectoryInfo[] dirs = dir.GetDirectories(); // Folders FileInfo[] files = dir.GetFiles();           // Files // Clear the ListView. Note that we call the Clear method on the  // Items collection rather than on the ListView itself.  // The Clear method of the ListView remove everything, including column // headers, and we only want to remove the items from the view. this.listViewFilesAndFolders.Items.Clear(); // Set the label with the current path. this.labelCurrentPath.Text = root; // Lock the ListView for updates. this.listViewFilesAndFolders.BeginUpdate(); // Loop through all folders in the root folder and insert them. foreach (DirectoryInfo di in dirs) { // Create the main ListViewItem. lvi = new ListViewItem(); lvi.Text = di.Name; // Folder name lvi.ImageIndex = 0; // The folder icon has index 0 lvi.Tag = di.FullName; // Set the tag to the qualified path of the  // folder // Create the two ListViewSubItems. lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = ""; // Size - a folder has no size and so this column  // is empty lvi.SubItems.Add(lvsi); // Add the subitem to the ListViewItem lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = di.LastAccessTime.ToString(); // Last accessed column lvi.SubItems.Add(lvsi); // Add the subitem to the ListViewItem. // Add the ListViewItem to the Items collection of the ListView. this.listViewFilesAndFolders.Items.Add(lvi); } // Loop through all the files in the root folder. foreach (FileInfo fi in files) { // Create the main ListViewItem. lvi = new ListViewItem(); lvi.Text = fi.Name; // Filename lvi.ImageIndex = 1; // The icon we use to represent a folder has  // index 1. lvi.Tag = fi.FullName; // Set the tag to the qualified path of the  // file. // Create the two subitems. lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = fi.Length.ToString(); // Length of the file lvi.SubItems.Add(lvsi); // Add to the SubItems collection lvsi = new ListViewItem.ListViewSubItem(); lvsi.Text = fi.LastAccessTime.ToString(); // Last Accessed Column lvi.SubItems.Add(lvsi); // Add to the SubItems collection // Add the item to the Items collection of the ListView. this.listViewFilesAndFolders.Items.Add(lvi); } // Unlock the ListView. The items that have been inserted will now  // be displayed. this.listViewFilesAndFolders.EndUpdate(); } catch (System.Exception err) { MessageBox.Show("Error: " + err.Message); } } 

How It Works

Before the first of the two foreach blocks, you call BeginUpdate() on the ListView control. Remember that the BeginUpdate() method on the ListView signals the ListView control to stop updating its visible area until EndUpdate() is called. If you did not call this method, filling the list view would be slower and the list may flicker as the items are added. Just after the second foreach block you call EndUpdate(), which makes the ListView control draw the items you filled it with.

The two foreach blocks contain the code you are interested in. You start by creating a new instance of a ListViewItem and then setting the Text property to the name of the file or folder you are going to insert. the ImageIndex of the ListViewItem refers to the index of an item in one of the ImageLists. Because of that, it is important that the icons have the same indexes in the two ImageLists. You use the Tag property to save the fully qualified path to both folders and files, for use when the user double-clicks the item.

Then, you create the two subitems. These are simply assigned the text to display and then added to the SubItems collection of the ListViewItem.

Finally, the ListViewItem is added to the Items collection of the ListView. The ListView is smart enough to simply ignore the subitems, if the view mode is anything but Details, so you add the subitems no matter what the view mode is now.

Note that there are some aspects of the code not discussed here — namely the lines that actually obtain information about the files:

// Get information about the root folder. DirectoryInfo dir = new DirectoryInfo(root);     // Retrieve the files and folders from the root folder. DirectoryInfo[] dirs = dir.GetDirectories(); // Folders FileInfo[] files = dir.GetFiles();           // Files

These lines use classes from the System.IO namespace for accessing files, so you need to add the following to the using region at the top of the code:

#region Using directives     using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Windows.Forms; using System.IO;     #endregion

You learn more about file access and System.IO in Chapter 22, but to give you an idea of what's going on, the GetDirectories() method of the DirectoryInfo object returns a collection of objects that represent the folders in the directory you're looking in, and the GetFiles() method returns a collection of objects that represent the files in the current directory. You can loop through these collections, as you did in the code above, using the object's Name property to return the name of the relevant directory or file, and create a ListViewItem to hold this string.

All that remains to be done for the list view to display the root folder is to call the two functions in the constructor of the form. At the same time, you instantiate the folderCol StringCollection with the root folder:

InitializeComponent();     // Init ListView and folder collection folderCol = new System.Collections.Specialized.StringCollection(); CreateHeadersAndFillListView(); PaintListView(@"C:\"); folderCol.Add(@"C:\"); 

To allow users to double-click an item in the ListView to browse the folders, you need to subscribe to the ItemActivate event. Select the ListView in the designer and double-click the ItemActivate event in the properties panel.

The corresponding event handler looks like this:

private void listViewFilesAndFolders_ItemActivate(object sender, EventArgs e) { // Cast the sender to a ListView and get the tag of the first selected // item. System.Windows.Forms.ListView lw = (System.Windows.Forms.ListView)sender; string filename = lw.SelectedItems[0].Tag.ToString(); if (lw.SelectedItems[0].ImageIndex != 0) { try { // Attempt to run the file. System.Diagnostics.Process.Start(filename); } catch { // If the attempt fails we simply exit the method. return; } } else { // Insert the items. PaintListView(filename); folderCol.Add(filename); } }

The Tag of the selected item contains the fully qualified path to the file or folder that was double-clicked. You know that the image with index 0 is a folder, so you can determine whether the item is a file or a folder by looking at that index. If it is a file, you attempt to load the file.

If it is a folder, you call PaintListView() with the new folder and then add the new folder to the folderCol collection.

Before you move on to the radio buttons, complete the browsing abilities by adding the Click event to the Back button. Double-click the button and fill the event handle with this code:

private void buttonBack_Click(object sender, EventArgs e) { if (folderCol.Count > 1) { PaintListView(folderCol[folderCol.Count - 2].ToString()); folderCol.RemoveAt(folderCol.Count - 1); } else { PaintListView(folderCol[0].ToString()); } }

If there is more than one item in the folderCol collection, then you are not at the root of the browser, and you call PaintListView() with the path to the previous folder. The last item in the folderCol collection is the current folder, which is why you need to take the second to last item. You then remove the last item in the collection and make the new last item the current folder. If there is only one item in the collection, you simply call PaintListView() with that item.

All that remains is to be able to change the view type of the list view. Double-click each of the radio buttons and add the following code:

private void radioButtonLargeIcon_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.listViewFilesAndFolders.View = View.LargeIcon; }     private void radioButtonList_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.listViewFilesAndFolders.View = View.List; }     private void radioButtonSmallIcon_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.listViewFilesAndFolders.View = View.SmallIcon; }     private void radioButtonDetails_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.listViewFilesAndFolders.View = View.Details; } private void radioButtonTile_CheckedChanged(object sender, EventArgs e) { RadioButton rdb = (RadioButton)sender; if (rdb.Checked) this.listViewFilesAndFolders.View = View.Tile; }

You check the radio button to see if it has been changed to Checked — if it has you set the View property of the ListView accordingly.

That concludes the ListView example. When you run it, you should see something like Figure 14-21.

image from book
Figure 14-21

image from book




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net