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

private void tree_AfterSelect (object sender, TreeViewEventArgs e)

{

  if (Полученный из параметра узел не является корнем)

     FillList (Создайте новый объект типа DirectoryInfo, который соответствует выбранной папке);

}

Метод FillList предстоит разработать. Его назначение — заполнить список (элемент list типа ListView), расположенный в правой части нашей формы, строками, которые содержат информацию о файлах в выбранной папке. На самом деле список заполняется объектами типа ListViewItem, которые можно конструировать на основе массива текстовых строк. Этими строками заполняются колонки списка, которые по традиции Microsoft называет SubItem. При работе с ListView надо усвоить особенности терминологии. Понятию Item соответствует строка списка, а понятию SubItem — столбец (или колонка). Для того, чтобы быстро создать объект класса ListViewItem создадим вспомогательный метод.

private string[] GetFileData (FileInfo file)

{

  return new string[]

  {

     file.Name,

    string.Format ("{0:f1}  K", file.Length / 1024.0), // file.Length.ToString(),

     file.CreationTime.ToShortDateString() + dateSep +

       file.CreationTime.ToShortTimeString(),

     file.LastWriteTime.ToString()//.ToShortDateString()  + dateSep + file.LastWriteTime.ToShortTimeString()

  };

}

Здесь показано, как форматировать данные разных типов. Разделитель dateSep используется только в одной колонке дат для того, чтобы вы смогли сравнить и оценить, нужен ли этот трюк. Метод GetFileData следует вызвать в процедуре заполнения списка, заготовка которой приведена ниже.

private void FillList (DirectoryInfo info)

{

  if (параметр не существует (Floppy or CD not inserted))

     return;

  FileInfo[] files;  // Получаем список файлов текущей директории

  try { files = info.GetFiles(); } catch { return; }

UpdateStatusBar (Color.WhiteSmoke, "Refreshing file list...");

  list.BeginUpdate();

  fileWatcher.Path = info.FullName;     // Настраиваем наблюдателя за файлами

  fileWatcher.EnableRaisingEvents = files.Length != 0;

  list.Items.Clear();

      // Создайте цикл прохода по файлам

     if (Атрибут файла не Hidden)

                 // Вставляем в список новый объект класса ListViewItem

  list.EndUpdate();

  UpdateStatusBar(Color.WhiteSmoke, "Ready");

}

Запустите и проверьте. Если вы справились с последним блоком заданий, то при выборе папки в дереве tree должен ожить и заполняться строками текста список файлов list.

Наблюдатель за файлами

Так как ожил список файлов, то логично разработать коды уже существующих обработчиков событий, порождаемых вторым наблюдателем (fileWatcher). Манипулирование списком несравненно проще управления деревом, поэтому подробных подсказок для разработки функций обработки событий Renamed и Changed не будет. Приведем лишь код вспомогательной функции, которая понадобится при поиске нужной строки.

private bool FindItem (string name)

{

  foreach (ListViewItem item in list.Items)

  {

     curItem = item;

     if (string.Compare (item.SubItems[0].Text, name, true) == 0)

       return true;

  }

  return false;

}

Здесь учтена деталь, на которую вы, наверное, давно обратили внимание: наблюдатели выдают имена объектов без учета регистра (все буквы строчные). Именно поэтому при поиске строки мы пользуемся статическим методом Compare, который позволяет сравнивать текстовые строки без учета регистра. Можно было бы поступить по-другому — явно приводить все строки к нижнему регистру (см. метод ToLower). Заметим, что именно так мы работали с деревом.

Еще одна деталь реализации наблюдателя касается особенностей работы с файлами, которыми обладает Microsoft Word. Попробуйте протестировать наблюдатель fileWatcher, многократно повторяя процедуру:

¨  Открыть Word-документ, который расположен в наблюдаемой папке,

¨  Ввести в документ исправление и записать,

В окне списка вы увидите настоящую свистопляску переименований и создания временных файлов (типа .tmp). Наблюдатель будет захлебываться событиями и весьма вероятно, что придется опять прибегнуть к помощи метода Invoke, так как, возможно, появятся исключения. Я справился без помощи Invoke, но отфильтровал (fileWatcher_Changed) файлы типа .tmp. Это можно сделать, например, так:

if (file.Extension.Equals(".tmp"))

  return;

Остался нереализованным еще один обработчик события, это list_ColumnClick. Он должен производить сортировку списка файлов, опираясь на данные выбранного столбца. Для того, чтобы ввести коды в пока пустое тело обработчика, необходимо вспомнить о существовании класса MyListViewComparer и разобраться в логике его использования. Кроме того, надо учесть эффект смены порядка сортировки, и согласовать его с четностью клика по заголовку. Приведем заготовку обсуждаемой функции.

private void list_ColumnClick (object sender, ColumnClickEventArgs e)

{

  bool repeated = // Повторное-ли нажатие? (Спросите listComparer он помнит);

  listComparer.col = e.Column;

  if (repeated)

     listComparer.order = // Поменяйте способ сортировки

  list.Sort();  // Отсортируйте

}

Вставьте код и проверьте способность приложения сортировать список файлов по всем четырем колонкам.

Скрытые папки

Перейдите в проект Client и откройте файл MainForm.cs в режиме дизайна. Вспомните, что на первой странице блока (TabControl) из четырех страниц (TabPage) размещена кнопка bHidden, которая должна включать и выключать режим видимости системных или скрытых папок. Для того, чтобы ввести обработчик события нажатия этой кнопки, совершите двойной щелчок над ней и введите в тело обработчика код, который приведен ниже.

private void bHidden_Click (object sender, EventArgs e)

{

  explorer.bHide = !explorer.bHide;

  explorer.RefreshTree();

}

Здесь мы обращаемся к DLL, а точнее, к элементу ExplorerControl, изменяем в нем значение флага bHide и вызываем функцию RefreshTree, которая должна выполнить достаточно сложный маневр над деревом, отображающим файловую систему. Он заключается в том, чтобы:

¨  Заморозить перерисовку дерева,

¨  Запомнить его текущее состояние,

¨  Уничтожить содержимое тех узлов, которые в данный момент раскрыты (и еще на один уровень вглубь),