Windows Management Instrumentation - инфраструктура управления операционной системой, страница 5

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

В левом окне будет изображено файловое дерево, а в правом — список файлов, хранящихся в папке, которая выбрана слева. Для того, чтобы список файлов, отображаемый в элементе 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", в который мы вложим все доступные логические диски. После этого в узлы, соответствующие дискам, мы вложим узлы, отображающие папки и т.д. Алгоритмы управления большими деревьями (а наше, как раз такое) довольно сложны и требуют достаточно высокой культуры программирования. Если задаться целью один раз (при запуске программы) заполнить все дерево, то из этого ничего хорошего не выйдет.