Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# ПІДРУЧНИКИ / c# / Manning - Windows.forms.programming.with.c#.pdf
Скачиваний:
108
Добавлен:
12.02.2016
Размер:
14.98 Mб
Скачать

ADD THE SUBITEMS FOR EACH ITEM IN THE LIST

 

Action

Result

 

 

 

1

Locate the LoadAlbumData

private void LoadAlbumData(string dir)

 

method in the MainForm.cs

{

 

source code window.

. . .

 

 

 

 

 

2

When the album is opened

foreach (string s in albumFiles)

 

successfully, create the three

{

 

subitems using the

. . .

 

ListViewItem item = new ListViewItem();

 

PhotoAlbum object.

 

 

 

 

item.Text

 

 

= Path.GetFileNameWithoutExtension(s);

 

 

if (album != null)

 

 

{

 

 

item.ImageIndex = MainForm.AlbumIndex;

 

 

// Add the subitems

 

 

item.SubItems.Add(album.Title);

 

 

bool hasPwd = (album.Password != null)

 

 

&& (album.Password.Length > 0);

 

 

item.SubItems.Add(hasPwd ? "y" : "n");

 

 

item.SubItems.Add(album.Count.ToString());

 

 

}

 

 

 

3

When the album fails to load,

else

 

set the subitems to

{

 

appropriate defaults.

item.ImageIndex = MainForm.ErrorIndex;

 

item.SubItems.Add(item.Text);

 

 

 

 

item.SubItems.Add("?");

 

 

item.SubItems.Add("0");

 

 

}

 

 

 

4

In either case, add the item

listViewMain.Items.Add(item);

 

to the list view.

}

 

 

}

 

 

 

Compile and run your code to ensure that it works. When you look at the Details view, note how the width of each column can be adjusted by clicking on the vertical line between two columns and dragging it to the left or right.

Congratulations, you have just completed your first list view! Your life may never be the same. Before you go off and celebrate, there is one other topic related to columns that is worth some discussion.

14.3.3SORTING A COLUMN

It is typical in applications such as Windows Explorer to sort the contents of a List-

View control column whenever a column title is clicked. The first time the title is clicked, the items are sorted based on the column’s contents in ascending order, or a to z order for strings; and a second click sorts in descending, or z to a, order. Whether to support this behavior in your applications depends on the nature of the application and the user environment for which it is targeted. Many Windows users expect such behavior, and may find it odd if an application does not support this feature. In this section we look at how to support this feature in Windows Forms applications, using our MyAlbumExplorer application as an example.

458

CHAPTER 14 LIST VIEWS

The ListView class provides three members of particular importance when you wish to support sorting in the Details view.

The Sorting property defines how the items are initially sorted. This is a SortOrder enumeration value, one of None for no sorting, Ascending, or Descending. This defaults to None, which is why our application currently

displays the items in random order.

The ColumnClick event occurs when a column is clicked. This is used to modify the control’s sorting behavior as appropriate for the selected column. Event handlers for this event receive a ColumnClickEventArgs parameter that contains a Column property indicating the column header clicked by the user.

The ListViewItemSorter property defines the IComparer interface used to compare two ListViewItem objects for the list. An overview of the IComparer interface is given in .NET Table 14.6.

We will use each of these members to define the sorting behavior for our application. We will define a class supporting the IComparer interface first, and then use this class to implement a ColumnClick event handler.

.NET Table 14.6 IComparer interface

The IComparer interface is an interface for comparing two objects, and is part of the Systems.Collections namespace. This namespace also provides two implementations of this interface for comparing string objects. The Comparer class supports case-sensitive comparisons, while the CaseInsensitiveComparer class supports case-insensitive comparisons. Both of these classes provide a Default property that returns an initialized instance of the class.

 

Compare

Returns an integer value indicating the equality

 

 

relationship between two object instances. The

Public Methods

 

value returned is less than zero, zero, or greater

 

than zero, corresponding to whether the first

 

 

 

 

object is less than, equal to, or greater than the

 

 

second, respectively.

 

 

 

For a ListView object, the comparison interface must accept two ListViewItem objects and return an appropriate value depending on the current column and sorting order. The ListView object itself defines the current sorting order based on the Sorting property value. We will need to keep track of the current column as part of our IComparer implementation.

We will begin by implementing a comparison class within our MainForm definition. We will use the rather noncreative name MyListViewComparer for this class.

LISTVIEW COLUMNS

459

To avoid hard-coding integer values into our code, the following steps also define constants for the column indices.

DEFINE A COMPARER CLASS FOR THE LIST VIEW

 

Action

Result

 

 

 

1

In the MainForm.cs source code

private const int AlbumNameColumn = 0;

 

window, define four constants for

private const int AlbumTitleColumn = 1;

 

each of the columns in our

private const int AlbumPwdColumn = 2;

 

private const int AlbumSizeColumn = 3;

 

ListView control.

 

 

 

 

 

2

Define the

private class MyListViewComparer : IComparer

 

MyListViewComparer class

{

 

within the MainForm class

// Associate a ListView with the class

 

// Track the current sorting column

 

definition.

 

// Compare method implementation

 

 

}

 

 

 

3

Associate a ListView object

// Associate a ListView with the class

 

with this class via the

private ListView _listView;

 

constructor.

public MyListViewComparer(ListView lv)

 

 

 

 

{

 

 

_listView = lv;

 

 

}

 

 

 

4

Also define a ListView property

public ListView ListView

 

to retrieve this setting.

{

 

 

get { return _listView; }

 

 

}

 

 

 

5

Allow the current sorting column

// Track the current sorting column

 

to be specified via a SortColumn

private int _sortColumn = 0;

 

property.

public int SortColumn

 

 

 

 

{

 

 

get { return _sortColumn; }

 

 

set { _sortColumn = value; }

 

 

}

 

 

 

6

Define the Compare method

// Compare method implementation

 

required by the IComparer

public int Compare(object a, object b)

 

interface.

{

 

 

 

 

 

7

In this method, convert the two

// Throws exception if not list items

 

objects into list view items.

ListViewItem item1 = (ListViewItem)a;

 

 

ListViewItem item2 = (ListViewItem)b;

 

 

 

8

Swap the two items if the current

// Account for current sorting order

 

sorting order is descending.

if (ListView.Sorting

 

Note: We could handle the sort

== SortOrder.Descending)

 

{

 

order as part of each compari-

ListViewItem tmp = item1;

 

son, but swapping the items up

item1 = item2;

 

item2 = tmp;

 

front seems easier.

 

}

 

 

 

460

CHAPTER 14 LIST VIEWS

DEFINE A COMPARER CLASS FOR THE LIST VIEW (continued)

 

Action

Result

 

 

 

9

Handle the case where the

// Handle nonDetails case

 

current view is not Details.

if (ListView.View != View.Details)

 

Note: The comparer is called

{

 

return CaseInsensitiveComparer.Default.

 

whenever the items must be

Compare(item1.Text, item2.Text);

 

sorted, regardless of the current

}

 

 

 

view.

 

 

Note how we use the default

 

 

Comparer instance provided by

 

 

the CaseInsensitiveCom-

 

 

parer class.

 

 

 

 

10

For the Details view, use a

return CompareAlbums(item1, item2);

 

separate method to compare the

}

 

two items.

 

 

 

 

11

For the CompareAlbums method,

public int CompareAlbums

 

the following steps are required.

(ListViewItem item1, ListViewItem item2)

 

a. Find the subitem instances

{

 

// Find the subitem instances

 

corresponding to each item.

ListViewItem.ListViewSubItem sub1

 

b. Return the appropriate result

= item1.SubItems[SortColumn];

 

ListViewItem.ListViewSubItem sub2

 

based on the current column.

= item2.SubItems[SortColumn];

 

 

// Return value is based on sort column

 

 

switch (SortColumn)

 

 

{

 

 

 

12

When one of the three string

case MainForm.AlbumNameColumn:

 

columns is selected, use the

case MainForm.AlbumTitleColumn:

 

default Comparer to compare the

case MainForm.AlbumPwdColumn:

 

{

 

two strings.

 

return

 

 

CaseInsensitiveComparer.

 

 

Default.Compare(

 

 

sub1.Text, sub2.Text);

 

 

}

 

 

 

13

When the Size column is

case MainForm.AlbumSizeColumn:

 

selected:

{

 

a. Convert the strings to integer

// Compare using integer values.

 

int x1 = Convert.ToInt32(sub1.Text);

 

values.

int x2 = Convert.ToInt32(sub2.Text);

 

b. Return the appropriate result.

if (x1 < x2)

 

Note: The ToInt32 method

return -1;

 

used here will throw an excep-

else if (x1 == x2)

 

return 0;

 

tion if the given string cannot be

 

else

 

converted to an integer.

return 1;

 

 

}

 

 

 

14

For any other column value,

default:

 

throw an exception indicating the

throw new IndexOutOfRangeException(

 

column was not recognized.

"unrecognized column index");

 

}

 

 

 

 

}

 

 

 

LISTVIEW COLUMNS

461

Соседние файлы в папке c#