我正在尝试列出计算机中的所有文件。以下代码符合我的期望。我的计算机C和D中有两个驱动器。如果用户选择D驱动器,则每个都可以。但是当选择C驱动器时(没有其中一个子文件夹)应用程序没有响应。
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
try
{
foreach (var directory in directoryInfo.GetDirectories())
{
//directoryNode.Nodes.Add(CreateDirectoryNode(directory));
TreeNode tn = CreateDirectoryNode(directory);
directoryNode.Nodes.Add(tn);
}
}
catch (UnauthorizedAccessException x)
{
}
return directoryNode;
}
答案 0 :(得分:0)
可能是因为C:
是操作系统驱动器,它会有很多文件夹。您是直接在C:
驱动器中为每个子命令递归调用此方法,根据我的经验,这将有数千个目录。
一种可能的解决方案是在树节点的直接子目录上显示,然后仅在扩展节点时加载子目录(按需加载)。或者显示进度条并使用BackgroundWorker
获取子目录,以便UI仍然响应。
答案 1 :(得分:0)
发生这种情况的一个合理原因是系统驱动器上存在大量文件夹。您应该加载“按需”项目,而不是一次性加载所有项目。
您应该在树中加载所有主文件夹,然后挂钩op TreeView.BeforeSelect
事件。在该事件中,您可以加载树的子项,可能在Task
中以使其异步。
一种简单的方法来存储您正在处理的项目的其他信息,即Tag
的{{1}}属性。如果已经加载了子项,则可以将其设置为要存储的自定义对象。
答案 2 :(得分:0)
为更多读者提供补充答案:
C:\ // <- C:\ is the selected/expanded node
|---Documents and Settings
|---Empty Folder
|---Program Files
|---Program Files (x86)
|---Windows
"*"
的子节点,而不展开该父节点。 (如您所知,实际目录名称不允许"*"
,但TreeView可以使用)可点击[+]
。
C:\
[+]-Documents and Settings
|--Empty Folder
[-]-Program Files
| |--[*] <- dummy Child Node (expanded here but collapsed in TreeView)
[+]-Program Files (x86)
[+]-Windows
BeforeExpand
事件,如果第一个子节点被调用"*"
,则删除该子节点,并加载该节点的子文件夹(同时添加"*"
每个包含更多子文件夹的子文件夹)
C:\
[+]-Documents and Settings
|--Empty Folder
[-]-Program Files
| [+]-ATI
| [+]-Classic Shell
| [+]-Common Files
| |--Empty Folder
| [+]-Microsoft
| [+]-TOSHIBA
| [+]-Windows NT
[+]-Program Files (x86)
[+]-Windows
BeforeExpand确保您在显示每个子文件夹之前加载它们。
注意:您的应用程序可能无法访问某些文件夹。一定要抓住这些例外。
使用另一个线程(或计时器)卸载已折叠了很长时间的子节点以释放内存。
您可以使用BackgroundWorker预加载TreeView中可见文件夹的子文件夹(但不能预加载它们的子文件夹)此步骤不是,因为如果您干扰,它可能会导致意外行为正在进行的工作(只有在您正确处理此类案件时才这样做)