Подтвердить что ты не робот

Заполнять дерево из списка путей

Я пытаюсь заполнить древовидное представление из списка пути к папке, например:

C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\AppPatch\MUI\040C
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409

с таким же образом:

├───addins
├───AppPatch
│   └───MUI
│       └───040C
├───Microsoft.NET
│   └───Framework
│       └───v2.0.50727
│           └───MUI
│               └───0409

Обратите внимание, что в списке нет "C:\WINDOWS\Microsoft.NET" или "C:\WINDOWS\Microsoft.NET\Framework". Я работаю над этим почти два дня, и в моем коде есть куча ошибок. Надеюсь, я смогу получить помощь здесь.

Спасибо.

Эрик

4b9b3361

Ответ 1

private void Form1_Load(object sender, EventArgs e)
    {
        var paths = new List<string>
                        {
                            @"C:\WINDOWS\AppPatch\MUI\040C",
                            @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
                            @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
                            @"C:\WINDOWS\addins",
                            @"C:\WINDOWS\AppPatch",
                            @"C:\WINDOWS\AppPatch\MUI",
                            @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
                        };

        treeView1.PathSeparator = @"\";

        PopulateTreeView(treeView1, paths, '\\');
}


private static void PopulateTreeView(TreeView treeView, IEnumerable<string> paths, char pathSeparator)
    {
        TreeNode lastNode = null;
        string subPathAgg;
        foreach (string path in paths)
        {
            subPathAgg = string.Empty;
            foreach (string subPath in path.Split(pathSeparator))
            {
                subPathAgg += subPath + pathSeparator;
                TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
                if (nodes.Length == 0)
                    if (lastNode == null)
                        lastNode = treeView.Nodes.Add(subPathAgg, subPath);
                    else
                        lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
                else
                    lastNode = nodes[0];
            }
        }
    }

alt text

Ответ 2

ehosca answer correcr, но есть небольшая проблема, когда я меняю пути таким образом

C:\WINDOWS\AppPatch\MUI\040C
D:\WIS\Microsoft.NET\Framework\v2.0.50727
E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI
C:\WINDOWS\addins
C:\WINDOWS\AppPatch
C:\WINDOWS\AppPatch\MUI
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409

enter image description here

Он будет всплывать в виде дерева.

Но добавив дополнительный код, мы можем избежать этой ситуации. Поэтому я изменил код в PopulateTreeView

private static void PopulateTreeView(TreeView treeView, string[] paths, char pathSeparator)
        {
            TreeNode lastNode = null;
            string subPathAgg;
            foreach (string path in paths)
            {
                subPathAgg = string.Empty;
                foreach (string subPath in path.Split(pathSeparator))
                {
                    subPathAgg += subPath + pathSeparator;
                    TreeNode[] nodes = treeView.Nodes.Find(subPathAgg, true);
                    if (nodes.Length == 0)
                        if (lastNode == null)
                            lastNode = treeView.Nodes.Add(subPathAgg, subPath);
                        else
                            lastNode = lastNode.Nodes.Add(subPathAgg, subPath);
                    else
                        lastNode = nodes[0];
                }
                lastNode = null; // This is the place code was changed

            }
        }

Теперь он отлично работает, как этот

enter image description here

Ответ 3

для версии linq'y:

public static TreeNode MakeTreeFromPaths(List<string> paths, string rootNodeName = "", char separator = '/')
{
    var rootNode = new TreeNode(rootNodeName);
    foreach (var path in paths.Where(x => !string.IsNullOrEmpty(x.Trim()))) {
        var currentNode = rootNode;
        var pathItems = path.Split(separator);
        foreach (var item in pathItems) {
            var tmp = currentNode.Nodes.Cast<TreeNode>().Where(x => x.Text.Equals(item));
            currentNode = tmp.Count() > 0 ? tmp.Single() : currentNode.Nodes.Add(item);
        }
    }
    return rootNode;
}

Ответ 4

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

private TreeNode PopulateTreeNode2(string[] paths, string pathSeparator)
    {
        if (paths == null)
            return null;

        TreeNode thisnode = new TreeNode();
        TreeNode currentnode;
        char[] cachedpathseparator = pathSeparator.ToCharArray();
        foreach (string path in paths)            {
            currentnode = thisnode;
            foreach (string subPath in path.Split(cachedpathseparator))
            {
                if (null == currentnode.Nodes[subPath])
                    currentnode = currentnode.Nodes.Add(subPath, subPath);
                else
                    currentnode = currentnode.Nodes[subPath];                   
            }
        }

        return thisnode;
    }

то вы можете использовать:

string[] paths =  {
                        @"C:\WINDOWS\AppPatch\MUI\040C",
                        @"D:\WINDOWS\Microsoft.NET\Framework\v2.0.50727",
                        @"E:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI",
                        @"C:\WINDOWS\addins",
                        @"C:\WINDOWS\AppPatch",
                        @"C:\WINDOWS\AppPatch\MUI",
                        @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MUI\0409"
                    };
TreeView treeview = new TreeView();
treeview.Nodes.Add(PopulateTreeNode2(paths, "\\"));

ПРИМЕЧАНИЕ. Возможно, в обоих решениях потребуется проверка строковой чувствительности, чтобы предотвратить создание некоторых папок.

потому что некоторый URL-адрес может указывать на одну и ту же папку на диске но были написаны разные, такие как:  Windows; WinDOWs, WINDOWS

Ответ 5

Вот какой-то очень старый код, который я когда-то использовал для создания дерева ASP.NET из кода (при условии, что TreeView имеет идентификатор TreeViewFolders):

protected void Page_Load(object sender, EventArgs e)
{
    GenerateTreeView(@"C:\WINDOWS\");
}

private void GenerateTreeView(string rootPath)
{
    GetFolders(System.IO.Path.GetFullPath(rootPath), TreeViewFolders.Nodes);
    TreeViewFolders.ExpandDepth = 1;
}

// recursive method to load all folders and files into tree
private void GetFolders(string path, TreeNodeCollection nodes)
{
    // add nodes for all directories (folders)
    string[] dirs = Directory.GetDirectories(path);
    foreach (string p in dirs)
    {
        string dp = p.Substring(path.Length);
        nodes.Add(Node("", p.Substring(path.Length), "folder"));
    }

    // add nodes for all files in this directory (folder)
    string[] files = Directory.GetFiles(path, "*.*");
    foreach (string p in files)
    {
        nodes.Add(Node(p, p.Substring(path.Length), "file"));
    }

    // add all subdirectories for each directory (recursive)
    for (int i = 0; i < nodes.Count; i++)
    {
        if (nodes[i].Value == "folder")
            GetFolders(dirs[i] + "\\", nodes[i].ChildNodes);
    }
}

// create a TreeNode from the specified path, text and type
private TreeNode Node(string path, string text, string type)
{
    TreeNode n = new TreeNode();
    n.Value = type;
    n.Text = text;
    return n;
}

Ответ 6

private void Form2_Load(object sender, EventArgs e)
    {
        treeView1.CheckBoxes = true;


        foreach (TreeNode node in treeView1.Nodes)
        {
            node.Checked = true;
        }

        string[] drives = Environment.GetLogicalDrives();

        foreach (string drive in drives)
        {
           // treeView1.Nodes[0].Nodes[1].Checked = true;
            DriveInfo di = new DriveInfo(drive);
            int driveImage;

            switch (di.DriveType)   
            {
                case DriveType.CDRom:
                    driveImage = 3;
                    break;
                case DriveType.Network:
                    driveImage = 6;
                    break;
                case DriveType.NoRootDirectory:
                    driveImage = 8;
                    break;
                case DriveType.Unknown:
                    driveImage = 8;
                    break;
                default:
                    driveImage = 2;
                    break;
            }

            TreeNode node = new TreeNode(drive.Substring(0, 1), driveImage, driveImage);
            node.Tag = drive;


            if (di.IsReady == true)
                node.Nodes.Add("...");

            treeView1.Nodes.Add(node);


        }

        foreach (TreeNode node in treeView1.Nodes)
        {
            node.Checked = true;
        }
    }

    private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
    {
        {
            if (e.Node.Nodes.Count > 0)
            {
                if (e.Node.Nodes[0].Text == "..." && e.Node.Nodes[0].Tag == null)
                {
                    e.Node.Nodes.Clear();


                    string[] dirs = Directory.GetDirectories(e.Node.Tag.ToString());

                    foreach (string dir in dirs)
                    {
                        DirectoryInfo di = new DirectoryInfo(dir);
                        TreeNode node = new TreeNode(di.Name, 0, 1);
                        node.Checked = true;

                        try
                        {
                            node.Tag = dir;


                            if (di.GetDirectories().Count() > 0)
                                node.Nodes.Add(null, "...", 0, 0).Checked = node.Checked;
                        }
                        catch (UnauthorizedAccessException)
                        {
                            node.ImageIndex = 12;
                            node.SelectedImageIndex = 12;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "DirectoryLister", MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        }
                        finally
                        {
                            node.Checked = e.Node.Checked;
                            e.Node.Nodes.Add(node);
                        }
                    }
                }
            }
        }              
    }

    private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
    {
        button1.Enabled = false;
        TreeNode node = e.Node;
        bool is_checked = node.Checked;
        foreach (TreeNode childNode in e.Node.Nodes)
        {
            childNode.Checked = e.Node.Checked;
        }
        treeView1.SelectedNode = node;
    }

Ответ 7

Этот код заполняет элемент управления TreeView для окон. Это намного проще, чем заданные ответы.

using System;
using System.Windows.Forms;
using System.IO;

// ...
    private void Form1_Load(object sender, EventArgs e)
    {
        treeView1.Nodes.Add(@"C:\");
        treeView1.Nodes[0].Tag = @"C:\";
        Populate((string)treeView1.Nodes[0].Tag, treeView1.Nodes[0]);
    }

    private void Populate(string address, TreeNode rootNode)
    {
        DirectoryInfo[] directories = new DirectoryInfo(address).GetDirectories();
        foreach (DirectoryInfo directory in directories)
        {
            TreeNode newNode = new TreeNode(directory.Name);
            rootNode.Nodes.Add(newNode);
            newNode.Tag = directory.FullName;

            try
            {
                DirectoryInfo[] innerDirectories = new DirectoryInfo(directory.FullName).GetDirectories();
                if (innerDirectories.Length > 0)
                    newNode.Nodes.Add(new TreeNode());

                FileInfo[] innerFiles = new DirectoryInfo(directory.FullName).GetFiles();
                if (innerFiles.Length > 0)
                    newNode.Nodes.Add(new TreeNode());
            }

            catch
            {
                continue;
            }
        }

        FileInfo[] files = new DirectoryInfo(address).GetFiles();
        foreach (FileInfo file in files)
            rootNode.Nodes.Add(file.Name);
    }

    private void treeView1_AfterExpand(object sender, TreeViewEventArgs e)
    {
        if (e.Node.Nodes.Count < 3)
        {
            e.Node.Nodes.Clear();
            Populate((string)e.Node.Tag, e.Node);
        }
    }

Ответ 8

Если вы не публикуете код, его невозможно определить, что с ним не так. Вместо того, чтобы тратить дни на это, почему бы не использовать сторонний элемент управления, например FolderView