12. Наконец, добавьте наш компонент ExplorerControl и задайте ему свойства: Name = explorer, Size = (776; 450), Location = (0, 33).
13. Запустите решение (из двух проектов) и убедитесь, что главное окно отбражает наш компонент.
Потренируйтесь в создании новых ветвей дерева, вставляя в конструктор класса ExplorerControl фрагменты кода. Например:
tree.Nodes.Add(new TreeNode("One",0,5));
tree.Nodes[0].Nodes.Add(new TreeNode("Two",1,5));
tree.Nodes[0].Nodes.Add(new TreeNode("Three",2,5));
Запустите, а затем обробуйте более служную структуру кроны дерева:
tree.Nodes.Add(new TreeNode("One",0,5));
TreeNode node = tree.Nodes[0];
node.Nodes.Add(new TreeNode("Two",1,5));
node.Nodes.Add(new TreeNode("Three",2,5));
node.Nodes[0].Nodes.Add(new TreeNode("Four",3,5));
node.Expand();
node.Nodes[0].Expand();
Просмотрите справку по классу TreeNode, выясните смысл параметров его коструктора, познакомьтесь с методами класса и научитесь управлять структурой и состоянием дерева программным способом (с помощью кода). Способны-ли вы теперь создать дерево с любой желаемой структурой? Если нет, то продолжайте тренировку до тех пор, пока не ответите на поставленный вопрос утвердительно.
Затем удалите из списка изображений все элементы, уничтожьте соответствующие bitmap-файлы и наполните treeImages изображениями дисков и папок. Учтите, что желательно (а в нашем проекте необходимо) иметь по два изображения для каждого элемента файловой системы. Они соответствуют неактивному и активному (Selected) состояниям. Так как мы собираемся ввести еще один (корневой) узел с именем "My Computer", то целесообразно договориться о способе нумерации (индексирования) иконок, используемых деревом. Пусть он будет таким:
Индекс |
Тип узла |
Состояние |
0 |
My Computer |
|
1 |
My Computer |
Selected |
2 |
LocalDisk |
|
3 |
LocalDisk |
Selected |
4 |
CDROM |
|
5 |
CDROM |
Selected |
6 |
Removable disk |
|
7 |
Removable disk |
Selected |
8 |
Network disk |
|
9 |
Network disk |
Selected |
10 |
Folder |
|
11 |
Folder |
Selected |
В левом окне будет изображено файловое дерево, а в правом — список файлов, хранящихся в папке, которая выбрана слева. Для того, чтобы список файлов, отображаемый в элементе ListView, можно было сортировать, нажимая на заголовки его столбцов, необходимо создать вспомогательный класс, реализующий интерфейс IComparer. Он нужен для того, чтобы гибко изменять функцию сравнения данных в зависимости от номера столбца списка. Вы догадываетесь, что в столбцах расположены данные разных типов. В первом столбце будут отображены имена файлов, во втором его размер (типа double так как мы собираемся выразить размер в килобайтах, а не байтах), в третьем — дата создания файла, в четвертом — дата изменения. Сортировка должна учитывать факт различия типов данных. Кроме того, режим сортировки (по возрастанию, или по убыванию), зависит от четности щелчка по данной колонке и это также необходимо учесть при сравнении двух объектов.
Интерфейс IComparer имеет всего один метод Compare, который должен вернуть (–1, 0, +1) в зависимости от результата сравнения двух объектов (знакомо, не правда-ли?). Но мы добавим логику, которая вызвана особенностями форматирования данных. Введите в состав класса ExplorerControl новую статическую переменную, которая повысит читабельность дат, отделяя дату содания файла от времени. Напомним, что время также является частью даты (объекта класса DateTime).
public static string dateSep = " "; // Разделитель даты и времени
Введите в пространство имен Library (после класса ExplorerControl, это важно) коды нового класса. Он поможет разобраться в проблеме сортировки списка из четырех колонок.
class MyListViewComparer : IComparer
{
public int col; // Номер колонки
public SortOrder order; // Режим сортировки
public MyListViewComparer() { col = 0; order = SortOrder.Ascending; }
public string MyTrim (string s) // Вспомогательный метод (убирает лишние пробелы)
{
if (col == 1) // В этой колонке при сортировке хотим отвязаться от буквы К (KiloBytes)
s = s.Trim (new char[] {'K'});
if (col == 2) // В этой колонке хотим убрать разделитель dateSep. Он введен для удобства чтения дат
{
int pos = s.IndexOf (ExplorerControl.dateSep);
s = s.Remove (pos, ExplorerControl.dateSep.Length-1);
}
return s;
}
public int Compare (object x, object y)
{
int res = 0;
string
s1 = MyTrim(((ListViewItem)x).SubItems[col].Text),
s2 = MyTrim(((ListViewItem)y).SubItems[col].Text);
switch (col)
{
case 0: // В нулевой колонке расположены имена файлов ( текстовые строки)
res = s1.CompareTo(s2);
break;
case 1: // В первой колонке расположены размеры файлов (double)
res = // Напишите код сравнения вещественных чисел, которые спрятаны в текстовых строках s1 и s2
break;
case 2: // Во второй и третьей колонках — даты (объекты DateTime)
case 3:
res = // Напишите код сравнения дат
break;
}
if (Режим сортировки по убыванию)
// Измените результат (одна строка кода)
return res;
}
}
Итак, интерфейс IComparer реализован и представлен миру классом MyListViewComparer. Мы задействуем его позже, когда будем развивать элемент типа ListView, а теперь пора подумать о дереве объектов файловой системы. В нем должен быть узел "My Computer", в который мы вложим все доступные логические диски. После этого в узлы, соответствующие дискам, мы вложим узлы, отображающие папки и т.д. Алгоритмы управления большими деревьями (а наше, как раз такое) довольно сложны и требуют достаточно высокой культуры программирования. Если задаться целью один раз (при запуске программы) заполнить все дерево, то из этого ничего хорошего не выйдет.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.