I'm trying to populate a treeview from a list of folder path, for example:
我正在尝试从文件夹路径列表中填充treeview,例如:
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
with an ouput like this:
配上这样的外罩:
├───addins
├───AppPatch
│ └───MUI
│ └───040C
├───Microsoft.NET
│ └───Framework
│ └───v2.0.50727
│ └───MUI
│ └───0409
Notice there's no 'C:\WINDOWS\Microsoft.NET' or 'C:\WINDOWS\Microsoft.NET\Framework' in the list. I've been working on this for almost two days and there's a bunch of bug in my code. Hope I can get help from here.
注意到没有“C:\ WINDOWS \微软。净”或“C:\ WINDOWS \微软。净框架\”列表中。我已经做了差不多两天了,我的代码里有很多bug。希望我能从这里得到帮助。
Thanks.
谢谢。
Eric
埃里克
8 个解决方案
#1
27
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];
}
}
}
#2
8
ehosca answer correcr, but there is a little problem, when I change paths to like this
ehosca回答正确,但有一个小问题,当我改变路径的时候。
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
It will popoulate treeview like this.
它会像这样弹出树视图。
But adding some extra code we can avoid this situation. So I changed the code in PopulateTreeView
但是添加一些额外的代码可以避免这种情况。所以我修改了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
}
}
Now it works fine like this
现在它可以像这样工作了
#3
8
for a linq'y version:
对于一个linq没有版本:
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
4
I took your code, and it work very well, but i made just a little modification for improving the load speed when it is used whit a large list of files it seems like find operation, and string operations generally are very slow
我取了你的代码,它运行得很好,但是我只做了一点修改,以提高加载速度,当它被使用时,它看起来像查找操作的一个大列表,字符串操作通常是非常慢的
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;
}
then you can use:
然后您可以使用:
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, "\\"));
NOTE: maybe some string sensitivity check will be needed in both solutions, in order to prevent some folders re creations.
注意:在两个解决方案中可能需要一些字符串敏感性检查,以防止某些文件夹重新创建。
because some url could be pointing to the same folder on the disk but spelled different such as: Windows ; WinDOWs , WINDOWS
因为有些url可能指向磁盘上相同的文件夹,但拼写不同,比如:Windows;窗户,窗户
#5
0
Here's some very old code I once used to create an ASP.NET treeview from code (assuming TreeView has an ID of TreeViewFolders):
下面是我曾经用来创建ASP的一些非常古老的代码。来自代码的nettreeview(假设treeview有TreeViewFolders的ID):
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
0
This code populates the TreeView control of windows forms. It is much more simpler than given answers.
此代码填充windows窗体的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);
}
}
#7
0
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;
}
#8
-2
Unless you post the code, its impossible to determine whats wrong with it. Instead of spending days on this why not use a 3rd party control such as the FolderView
除非你发布代码,否则不可能确定它有什么问题。与其花几天时间在这上面,为什么不使用第三方控制,比如FolderView
#1
27
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];
}
}
}
#2
8
ehosca answer correcr, but there is a little problem, when I change paths to like this
ehosca回答正确,但有一个小问题,当我改变路径的时候。
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
It will popoulate treeview like this.
它会像这样弹出树视图。
But adding some extra code we can avoid this situation. So I changed the code in PopulateTreeView
但是添加一些额外的代码可以避免这种情况。所以我修改了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
}
}
Now it works fine like this
现在它可以像这样工作了
#3
8
for a linq'y version:
对于一个linq没有版本:
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
4
I took your code, and it work very well, but i made just a little modification for improving the load speed when it is used whit a large list of files it seems like find operation, and string operations generally are very slow
我取了你的代码,它运行得很好,但是我只做了一点修改,以提高加载速度,当它被使用时,它看起来像查找操作的一个大列表,字符串操作通常是非常慢的
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;
}
then you can use:
然后您可以使用:
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, "\\"));
NOTE: maybe some string sensitivity check will be needed in both solutions, in order to prevent some folders re creations.
注意:在两个解决方案中可能需要一些字符串敏感性检查,以防止某些文件夹重新创建。
because some url could be pointing to the same folder on the disk but spelled different such as: Windows ; WinDOWs , WINDOWS
因为有些url可能指向磁盘上相同的文件夹,但拼写不同,比如:Windows;窗户,窗户
#5
0
Here's some very old code I once used to create an ASP.NET treeview from code (assuming TreeView has an ID of TreeViewFolders):
下面是我曾经用来创建ASP的一些非常古老的代码。来自代码的nettreeview(假设treeview有TreeViewFolders的ID):
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
0
This code populates the TreeView control of windows forms. It is much more simpler than given answers.
此代码填充windows窗体的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);
}
}
#7
0
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;
}
#8
-2
Unless you post the code, its impossible to determine whats wrong with it. Instead of spending days on this why not use a 3rd party control such as the FolderView
除非你发布代码,否则不可能确定它有什么问题。与其花几天时间在这上面,为什么不使用第三方控制,比如FolderView