Как показать все данные / папки на диске в виде дерева?

 cmbDrives.DataSource = Environment.GetLogicalDrives();

У меня есть этот код для отображения всех накопителей в выпадающем списке, и я хочу показать все данные, связанные с накопителем в treeview на comboboxselectionchanged событие.

Как я могу это сделать?

1 ответ

В следующем коде достигается то, что вы хотите, используя фонового работника, чтобы убедиться, что пользовательский интерфейс остается отзывчивым, пока выполняется прогресс во время обхода папки.

Сначала добавьте ComboBox, Treeview и BackgroundWorker на поверхность вашего дизайна. Обязательно добавьте события, использованные в следующем коде, из окна "Свойства" для каждого элемента управления, использующего вид события. Убедитесь, что установили свойство WorkerReportsProgress истинно для BackgroundWorker.

Сначала событие ComboBox SelectionIndexChanged:

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

Мы отключаем наш комбинированный список, чтобы предотвратить выбор нового значения во время обработки обхода диска. Затем мы запускаем наш BackgroundWorker, передавая ему SelectedItem, который мы считаем допустимым диском.

Фоновый работник

Событие DoWork принимает eventargs со свойством Argument, которое содержит значение, которое мы указали при вызове RunWorkerAsync. Поскольку теперь мы работаем с потоком, не относящимся к пользовательскому интерфейсу, нам понадобятся некоторые хитрости для обновления пользовательского интерфейса. Фоновый рабочий может сделать это с помощью метода ReportProgress. Требуется целое число, обычно используемое для определения расстояния и необязательное пользовательское состояние. Мы используем эти два параметра, чтобы указать, в каком состоянии мы находимся, и предоставляем TreeNode, который необходимо добавить или обновить в нашем TreeView. Тогда позвони 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 (или Tuple of TreeNodes), поэтому мы можем добавлять узлы в TreeView или один из его узлов, пока мы находимся в потоке пользовательского интерфейса. 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;
}

Обход папки на диске

Для обхода дерева каталогов я использую рекурсивную функцию (слабо вдохновленную ответом Криса Балларда, который вызывает BackgroundWorkers ReportProgress метод, когда он имеет TreeNode, который готов для добавления в TreeView. Обратите внимание, как я использую Tuple в качестве объекта состояния, который содержит родительский и дочерний элементы, которые необходимо добавить, но это конкретное действие остается для события ProgressChanged в UI-Thread.

    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
                    ));
        }
    }
Другие вопросы по тегам