preencher TreeView de uma lista de caminho

Eu estou tentando preencher um treeview de uma lista de caminho de pasta, por exemplo:

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 

com uma saída como esta:

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

Observe que não há ‘C: \ WINDOWS \ Microsoft.NET’ ou ‘C: \ WINDOWS \ Microsoft.NET \ Framework’ na lista. Eu tenho trabalhado nisso por quase dois dias e há um monte de bug no meu código. Espero que eu possa obter ajuda daqui.

Obrigado.

Eric

 private void Form1_Load(object sender, EventArgs e) { var paths = new List { @"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 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]; } } } 

texto alternativo

ehosca resposta correcr, mas há um pequeno problema, quando eu mudo caminhos para gostar disso

 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 

insira a descrição da imagem aqui

Ele popoulate treeview como este.

Mas adicionando algum código extra, podemos evitar essa situação. Então eu mudei o código no 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 } } 

Agora funciona bem assim

insira a descrição da imagem aqui

para uma versão linq’y:

 public static TreeNode MakeTreeFromPaths(List 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().Where(x => x.Text.Equals(item)); currentNode = tmp.Count() > 0 ? tmp.Single() : currentNode.Nodes.Add(item); } } return rootNode; } 

Eu peguei seu código, e ele funcionou muito bem, mas eu fiz apenas uma pequena modificação para melhorar a velocidade de carregamento quando ele é usado com uma grande lista de arquivos que parece operação de busca, e operações de string geralmente são muito lentas

 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; } 

então você pode usar:

 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, "\\")); 

OBSERVAÇÃO: talvez seja necessária alguma verificação de sensibilidade de seqüência de caracteres em ambas as soluções, a fim de evitar algumas re-criações de pastas.

porque algum URL poderia estar apontando para a mesma pasta no disco, mas com uma grafia diferente, como: Windows; WinDOWs, WINDOWS

Aqui está um código muito antigo que eu usei uma vez para criar uma treeview do ASP.NET a partir do código (assumindo que o TreeView tem um ID de 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; } 

Esse código preenche o controle TreeView dos formulários do Windows. É muito mais simples que respostas dadas.

 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); } } 
 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; } 

A menos que você postar o código, é impossível determinar o que está errado com ele. Em vez de gastar dias com isso, por que não usar um controle de terceiros, como o FolderView?