Объекты файловой системы (как папки, так и файлы) могут изменить некоторые из своих атрибутов, например, стать скрытыми, или наоборот. Наблюдатели фиксируют эти изменения и возбуждают событие Changed. Рассмотрим код реакции на это событие.
void watcher_Changed(object sender, FileSystemEventArgs e)
{
try
{
DirectoryInfo dir = new DirectoryInfo(e.FullPath);
bool isFolder = (uint)(dir.Attributes & FileAttributes.Directory) != 0;
if (isFolder)
ChangeTree(dir);
else
{
if (tree.SelectedNode != null &&
tree.SelectedNode == FindNode(Path.GetDirectoryName(e.FullPath)))
FillFileList(tree.SelectedNode);
}
SetMessage("Changed: " + dir.FullName + ". Attributes: " + GetAttributes(dir));
}
catch (Exception ex){ SetMessage("Changed: " + ex.Message); }
}
Здесь мы выясняем тип объекта (папка или файл), и если это папка, то выбираем способ реагирования на ее изменение в методе ChangeTree. Все изменения атрибутов отмечаются в журнале событий.
void ChangeTree(DirectoryInfo dir)
{
TreeNode node = FindNode(dir.FullName);
bool bHidden = Определите наличие атрибутов hidden
if (node == null)
{
if (Показываем скрытые объекты или объект не скрыт)
AddFolder(dir.FullName);
}
else
{
if (showHidden)
{
if (bHidden)
node.ImageIndex = 16;
else
node.ImageIndex = 14;
}
else
node.Remove();
}
}
Внешние изменения атрибутов объекта (в зависимости от установки флага showHidden) могут привести к появлению, исчезновению узлов в нашем дереве. При отображении скрытых объектов(showHidden== true) внешние изменения могут повлечь лишь смену облика папки в дереве, но в любом случае необходимо корректировать дерево TreeView. В методе ChangeTree рассматриваются четыре варианта изменений. Если:
¨ Появилась папка и установлен флаг показа скрытых объектов, или появилась обычная папка, то в дерево надо добавить новый узел, соответствующий этой папке.
¨ Папка стала скрытой и установлен флаг показа скрытых объектов, то надо изменить изображение папки.
¨ Папка стала обычной и установлен флаг показа скрытых объектов, то надо изменить изображение папки.
¨ Папка стала скрытой и снят флаг показа скрытых объектов, то надо удалить из дерева узел, соответствующий этой папке.
При реализации реакции на возбуждаемое наблюдателем событие Created для файлов мне не повезло (пришлось провести часов 10 в режиме отладки). Первым вариантом (который казался вполне логичным) был такой код:
string parent = Path. . . . // файловый путь родительской папки
TreeNode node = FindNode(файловый путь родительской папки);
if (node != null)
node.Nodes.Add(new TreeNode(GetFolderName(fullPath), id, id + 1));
Он все делает правильно, но я забыл установить свойство SynchronizingObject = this; и неожиданно обнаружил необработанное исключение, которое сообщает, либо о том, что поток остановился, либо о том, что вызов должен производиться из другого потока с помощью метода Invoke. Помилуйте, какие потоки? Мы не создавали дополнительных потоков. Теперь я жалею, что не сразу стал читать документацию по методу Invoke, которым обладают все классы, производные от Control. Я сэкономил бы часы, проведенные в отладке.
Будучи уверенным, что знаю, как работает метод Invoke интерфейса IDispatch (см. технологию COM), и будучи уверенным, что COM (слава Богу) где-то далеко от того места, где мы сейчас находимся (мы ведь работаем с классами .NET), я думал, что указание на Invoke — это бред компилятора, вызванный каким-то моим крупным промахом. Теперь я знаю, что FileSystemWatcher реализован в технологии COM и это печально, так как эта технология (основанная на интерфейсе IDispatch), является довольно унылой и на мой взгляд, тупиковой ветвью развития.
Читаем справку по методу Control.Invoke, которая необычайно богата и красноречива. Вот она вся:
Executes the specified delegate on the thread that owns the control's underlying window handle.
Все же английский язык в изощренных умах бывает очень емким. Эти слова (все вместе) означают, что:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.