如何在树视图中显示所有与驱动器相关的数据/文件夹

本文关键字:驱动器 数据 文件夹 视图 显示 | 更新日期: 2023-09-27 18:02:43

 cmbDrives.DataSource = Environment.GetLogicalDrives();

我有这个代码来显示组合框中的所有驱动器,并希望在comboboxselectionchanged事件上显示treeview中所有驱动器的相关数据。

我该怎么做呢?

如何在树视图中显示所有与驱动器相关的数据/文件夹

下面的代码通过利用backgroundworker来确保UI在文件夹遍历过程中保持响应,从而实现了您想要的效果。

首先添加一个ComboBox,一个Treeview和一个BackgroundWorker到你的设计图面上。确保使用eventview从Properties窗口为每个控件添加下面代码中使用的事件。确保为BackgroundWorker设置属性WorkerReportsProgress为true。

首先是ComboBox SelectionIndexChanged事件:

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    this.comboBox1.Enabled = false;
    this.backgroundWorker1.RunWorkerAsync(comboBox1.SelectedItem.ToString());
}

我们禁用组合框以防止在处理驱动器遍历时选择新值。然后我们启动BackgroundWorker,将SelectedItem传递给它,假设它是一个有效的驱动器。

<<h3>背景工人/h3>

DoWork事件接受一个eventargs,它有一个Argument属性,包含我们在调用RunWorkerAsync时提供的值。由于我们现在在一个非UI线程上,我们需要一些技巧来更新UI。后台工作程序可以用它的ReportProgress方法来做这件事。它接受一个整数(通常用于表示我们所走的距离)和一个可选的userstate。我们使用这两个来指示我们所处的状态,并提供一个需要在我们的TreeView上添加或更新的TreeNode。然后调用GetDirectoryNodes进行目录遍历。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    TreeNode node = new TreeNode(e.Argument.ToString());
    backgroundWorker1.ReportProgress(0, node);
    GetDirectoryNodes(e.Argument.ToString(), node);
}

ProgressChanged被调用,每次我们有一个TreeNode(或TreeNode的元组),所以我们可以添加节点到TreeView或它的节点之一,而我们在UI线程。ProgressPercentage不是用来显示我们走了多远,而是用来区分初始状态和遍历状态。

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    switch (e.ProgressPercentage)
    {
        case 0:
            // we have s TreeNode, this is our root.
            treeView1.Nodes.Add((TreeNode) e.UserState);
            break;
        case 1:
            // we get a tuple, the parent and it's intended child.
            var tup = (Tuple<TreeNode,TreeNode>) e.UserState;
            tup.Item1.Nodes.Add(tup.Item2);
            break;
        default:
            break;
    }
}

一旦我们完成(即遍历每个文件夹),我们再次启用组合框,以便我们可以选择一个新的驱动器。

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    this.comboBox1.Enabled = true;
}

驱动器文件夹遍历

要遍历目录树,我使用递归函数(松散地灵感来自Chris Ballard的答案,一旦它有准备添加到TreeView的TreeNode,就调用BackgroundWorkers ReportProgress方法)。请注意,我是如何使用Tuple作为状态对象,其中包含要添加的Parent和Child,但该特定操作留给UI-Thread上的ProgressChanged事件。

    private void GetDirectoryNodes(string path, TreeNode node)
    {
        try
        {
            var subDirs = Directory.GetDirectories(path);
            foreach (string p in subDirs)
            {
                var subnode = new TreeNode(p);
                backgroundWorker1.ReportProgress(
                    1, 
                    new Tuple<TreeNode, TreeNode>(
                        node, subnode
                        ));
                GetDirectoryNodes(p, subnode); // recursive!
            }
        }
        catch (Exception exp)
        {
            var subnode = new TreeNode(path+"''error");
            subnode.ToolTipText = exp.Message;
            backgroundWorker1.ReportProgress(
                1, 
                new Tuple<TreeNode, TreeNode>(
                    node, subnode
                    ));
        }
    }