【问题标题】:Recursive directory listing using WinForms TreeView?使用 WinForms TreeView 的递归目录列表?
【发布时间】:2011-01-16 19:22:54
【问题描述】:

我想制作一个树形视图,显示系统上的所有文件夹,并且只显示音乐文件,例如 .mp3 .aiff .wav 等。

我记得读到我需要使用递归函数或类似的东西。

【问题讨论】:

  • 你为什么在你的问题上加上“active-directory”标签?这与AD无关......
  • 顺便问一下,它是什么技术? Windows 窗体、WPF、ASP.NET、Silverlight ?

标签: c# treeview filesystems populate


【解决方案1】:

通常大多数计算机都有数千个文件夹和数十万个文件,因此以递归方式在 TreeView 中显示所有这些文件夹非常慢且消耗大量内存,请在 this question 中查看我的答案,并引用我的一些答案修改什么时候可以得到一个非常有用的 GUI:

// Handle the BeforeExpand event
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
   if (e.Node.Tag != null) {
       AddDirectoriesAndMusicFiles(e.Node, (string)e.Node.Tag);
   }
}

private void AddDirectoriesAndMusicFiles(TreeNode node, string path)
{
    node.Nodes.Clear(); // clear dummy node if exists

    try {
        DirectoryInfo currentDir = new DirectoryInfo(path);
        DirectoryInfo[] subdirs = currentDir.GetDirectories();

        foreach (DirectoryInfo subdir in subdirs) {
            TreeNode child = new TreeNode(subdir.Name);
            child.Tag = subdir.FullName; // save full path in tag
            // TODO: Use some image for the node to show its a music file

            child.Nodes.Add(new TreeNode()); // add dummy node to allow expansion
            node.Nodes.Add(child);
        }

        List<FileInfo> files = new List<FileInfo>();
        files.AddRange(currentDir.GetFiles("*.mp3"));
        files.AddRange(currentDir.GetFiles("*.aiff"));
        files.AddRange(currentDir.GetFiles("*.wav")); // etc

        foreach (FileInfo file in files) {
            TreeNode child = new TreeNode(file.Name);
            // TODO: Use some image for the node to show its a music file

            child.Tag = file; // save full path for later use
            node.Nodes.Add(child);
        }

    } catch { // try to handle use each exception separately
    } finally {
        node.Tag = null; // clear tag
    }
}

private void MainForm_Load(object sender, EventArgs e)
{
    foreach (DriveInfo d in DriveInfo.GetDrives()) {
        TreeNode root = new TreeNode(d.Name);
        root.Tag = d.Name; // for later reference
        // TODO: Use Drive image for node

        root.Nodes.Add(new TreeNode()); // add dummy node to allow expansion
        treeView1.Nodes.Add(root);
    }
}

【讨论】:

  • 好朋友!耻辱没有被标记为正确答案 - 我认为它应该是因为它似乎很好地解决了这个问题。
  • 谢谢,我在数据库节点表群体中使用了类似的代码。 datadevelop.codeplex.com 所以刷新很简单,只需设置 node.Tag = null。
  • 使用虚拟节点来放弃不必要的检索真是个好主意。跳出框框的思维方式。
  • 超级!这真的很方便!
【解决方案2】:

递归搜索所有驱动器以查找特定文件不会很好地工作。对于今天的大型驱动器,这大约需要一分钟。

Windows 资源管理器使用的一个标准技巧是仅列出顶级目录和文件。它在目录节点中放置一个虚拟节点。当用户打开节点(BeforeExpand 事件)时,它仅搜索该目录并将虚拟节点替换为在该目录中找到的目录和文件。再次在目录中放置一个虚拟节点。等等。

您可以通过添加一个空的子目录来查看这一点。目录节点将显示为 + 字形。当您打开它时,资源管理器发现没有要列出的目录或文件并删除虚拟节点。 + 字形消失。

这非常快,列出单个目录的内容不到一秒钟。但是在您的情况下使用这种方法存在问题。目录包含合适的音乐文件的可能性很小。用户会经常因为发现在一组子目录中导航没有产生任何结果而感到沮丧。

这就是为什么 Windows 有一个专门的地方来存储特定的媒体文件。我的音乐在这种情况下。使用 Environment.GetFolderPath(Environment.SpecialFolder.MyMusic) 找到它。迭代它应该不会花很长时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2018-09-17
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多