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

ADD THE PHOTOS IN AN ALBUM TO THE LIST

 

Action

Result

 

 

 

1

Modify the LoadPhotoData

private void LoadPhotoData(PhotoAlbum album)

 

method to simply return if the

{

 

given album is null or empty.

. . .

 

// Handle null or empty album

 

 

 

 

if (album == null || album.Count == 0)

 

 

return;

 

 

 

2

Iterate over the photographs in

// Load the photo items

 

the album.

for (int i = 0; i < album.Count; i++)

 

How-to

{

 

 

 

Use a for loop to permit access

 

 

to the index values.

 

 

 

 

3

Create a new ListViewItem for

Photograph photo = album[i];

 

each photo.

ListViewItem item = new ListViewItem();

 

 

 

4

Assign the caption as the item

item.Text = photo.Caption;

 

label, and the image list index to

item.Tag = i;

 

our small photograph image.

item.ImageIndex = MainForm.PhotoIndex;

 

 

 

 

 

5

Add the subitem values.

// Add the subitems

 

How-to

item.SubItems.Add(photo.

 

DateTaken.ToShortDateString());

 

a. Use the short date format

item.SubItems.Add(photo.Photographer);

 

for the Taken column.

item.SubItems.Add(photo.FileName);

 

 

 

b. Also place the photo’s index

 

 

value in a hidden subitem.

 

 

 

 

6

Add the new item to the control.

listViewMain.Items.Add(item);

 

 

}

 

 

}

 

 

 

This code initializes the control with the contents of the open album. Note in particular how we define the Tag property to hold the integer index. Since the Tag property holds an object instance, this line boxes the integer value in order to store it as a reference type. Boxing was mentioned in chapter 5, and is discussed in detail in appendix A.

You can compile and run this code if you like. Double-click on an album to activate it and display the contained photographs. Most of the support for photographs is still missing, so you’ll find it rather easy to cause an error.

The remainder of this section implements the support required for both albums and photographs to coexist in our ListView control. We begin with column sorting.

14.5.4SORTING A COLUMN (AGAIN)

Our users will want to sort the columns for both the album and photograph display, so we need to make some changes in our MyListViewComparer class to enable this support. Of key importance is the ability to tell which type of object we are comparing. When comparing photos, we also need to know the PhotoAlbum they come

ITEM ACTIVATION

477

from. We can handle both requirements through a private album field. When the album is null, we are comparing PhotoAlbum objects. When an album is assigned, we are comparing Photograph instances.

Let’s add this field and update our Compare method to make use of this value.

IDENTIFY THE TYPE OF OBJECT TO COMPARE

 

Action

Result

 

 

 

1

Locate the MyListViewComparer

private class MyListViewComparer

 

class defined in the MainForm.cs

: IComparer

 

source file.

{

 

. . .

 

 

 

 

 

2

Add a PhotoAlbum field and

PhotoAlbum _album = null;

 

corresponding property.

public PhotoAlbum CurrentAlbum

 

 

{

 

 

get { return _album; }

 

 

set { _album = value; }

 

 

}

 

 

 

3

Use this property to identify which

public int Compare(object a, object b)

 

object to compare in the Compare

{

 

method.

. . .

 

// Handle the nonDetails case

 

 

 

Note: Since the label for both types

if (ListView.View != View.Details)

 

of items is a string, the existing

{

 

return CaseInsensitiveComparer.

 

code for the non-Details case will

 

Default.Compare(

 

work for both objects.

item1.Text, item2.Text);

 

 

}

 

 

if (CurrentAlbum == null)

 

 

return CompareAlbums(item1, item2);

 

 

else

 

 

return ComparePhotos(item1, item2);

 

 

}

 

 

}

 

 

 

Now all we have to do is implement the ComparePhotos method to compare two Photograph items. Much of this will be similar to the CompareAlbums method. The one difference is when we need to compare items using the Taken column. This column holds a date value, so a string comparison is not appropriate. It turns out the DateTime structure provides a Compare method for just this purpose.

We can use this method in the ComparePhotos method to our comparer class.

478

CHAPTER 14 LIST VIEWS

.

IMPLEMENT METHOD TO COMPARE TWO PHOTO ITEMS

 

Action

Result

 

 

 

4

Add a new ComparePhotos

public int ComparePhotos

 

method to the MyListView-

(ListViewItem item1, ListViewItem item2)

 

Comparer class.

{

 

ListViewItem.ListViewSubItem sub1;

 

 

 

 

ListViewItem.ListViewSubItem sub2;

 

 

switch (SortColumn)

 

 

{

 

 

 

5

For the columns containing text

case MainForm.PhotoCaptionColumn:

 

strings, use the default

case MainForm.PhotoPhotographerColumn:

 

comparer provided by the

case MainForm.PhotoFileNameColumn:

 

sub1 = item1.SubItems[SortColumn];

 

CaseInsensitiveComparer

 

sub2 = item2.SubItems[SortColumn];

 

class.

return CaseInsensitiveComparer.

 

 

Default.Compare(sub1.Text,

 

 

sub2.Text);

 

 

 

6

For the Taken column, determine

case MainForm.PhotoDateTakenColumn:

 

the index into the album for each

// Find the indices into the album

 

photo.

int index1 = (int)item1.Tag;

 

int index2 = (int)item2.Tag;

 

 

 

 

 

7

Then determine the

// Look up the dates for each photo

 

corresponding DateTime value

DateTime date1

 

for each photo.

= CurrentAlbum[index1].DateTaken;

 

DateTime date2

 

 

 

 

= CurrentAlbum[index2].DateTaken;

 

 

 

8

Use the Compare method

return DateTime.Compare(date1, date2);

 

provided by the DateTime

 

 

structure to calculate the result.

 

 

 

 

9

Throw an exception if an

default:

 

unrecognized column is

throw new IndexOutOfRangeException(

 

provided.

"unrecognized column index");

 

}

 

 

 

 

}

 

 

 

The last change required for column sorting is to update the CurrentAlbum property for our comparer field whenever the contents of the ListView control are refreshed. This ensures that our Compare implementation performs the proper comparison based on the contents of the control.

UPDATE THE CURRENTALBUM PROPERTY WHEN REQUIRED

 

Action

Result

 

 

 

10

Update the LoadPhotoData

private void LoadPhotoData(PhotoAlbum album)

 

method to assign the current

{

 

album to the comparer.

. . .

 

_albumsShown = false;

 

 

 

 

_album = album;

 

 

_comparer.CurrentAlbum = _album;

 

 

. . .

 

 

}

 

 

 

ITEM ACTIVATION

479

UPDATE THE CURRENTALBUM PROPERTY WHEN REQUIRED (continued)

 

Action

Result

 

 

 

11

Update the LoadAlbumData

private void LoadAlbumData(string dir)

 

method to assign a null album

{

 

to the comparer.

listViewMain.Clear();

 

_comparer.CurrentAlbum = null;

 

 

 

 

. . .

 

 

}

 

 

 

Our application can now sort both photographs and albums. Once again you can compile and run the program if you are careful not to use any photograph functionality we have not yet implemented. Our next task is the Properties dialog.

14.5.5UPDATING THE PROPERTIES MENU

You may think we are moving through this code rather quickly, and you would be right. While these changes are required as a result of our defined item activation behavior, there are not a lot of new concepts to cover. This is especially true here. As a result, we will simply run through the steps in the following table and then move on to our final topic of editing the item label.

UPDATE THE CLICK HANDLER FOR THE PROPERTIES MENU

 

Action

Result

 

 

 

1

In the MainForm.cs code

private void menuProperties_Click

 

window, update the Click event

(object sender, System.EventArgs e)

 

handler for the Properties menu

{

 

if (listViewMain.SelectedItems.Count <= 0)

 

to call a new DisplayPhoto-

 

return;

 

Properties method when

ListViewItem item

 

photographs are shown in the

 

control.

= listViewMain.SelectedItems[0];

 

if (this._albumsShown)

 

 

 

 

DisplayAlbumProperties(item);

 

 

else

 

 

DisplayPhotoProperties(item);

 

 

}

 

 

 

2

Add the new DisplayPhoto-

private void DisplayPhotoProperties

 

Properties method.

(ListViewItem item)

 

 

{

 

 

 

3

Determine the index of the

if (!(item.Tag is int))

 

selected photo in the current

return;

 

album.

int index = (int)item.Tag;

 

 

 

Note: While the is keyword

 

 

works fine with integer types,

 

 

the as keyword can only be used

 

 

with reference types.

 

 

 

 

4

Assign the current position in the

_album.CurrentPosition = index;

 

album to this index.

 

 

 

 

480

CHAPTER 14 LIST VIEWS

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