フォルダパスのリストからツリービューにデータを入力しようとしています。次に例を示します。
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」がないことに注意してください。私はこれにほぼ2日間取り組んできましたが、コードにたくさんのバグがあります。ここから助けが得られることを願っています。
ありがとう。
エリック
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];
}
}
}
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;
}
ehoscaは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
このようにツリービューを作成します。
ただし、コードを追加することで、この状況を回避できます。そこで、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
}
}
今ではこのように正常に動作します
私はあなたのコードを取りました、そしてそれは非常にうまくいきます、しかし私はそれがファイルの大きなリストが検索操作のように見え、そして文字列操作が一般的に非常に遅いときにそれが使われるときのロード速度を改善するために少し変更を加えました
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フォームの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);
}
}
for
サイクルだけを使用してパスリストからツリーを作成することができました。そして、それは現時点でこの質問の最も簡単な答えであるように見えます。
このコードブロックを使用して、ツリーを作成します。 list
は、ファイルまたはフォルダのリストです。treeView1
はTreeViewです。
//Creates a tree from given path list
foreach (string path in list)
{
TreeNodeCollection nodes = treeView1.Nodes;
foreach (string path_part in path.Split('\\'))
{
//Here it adds a new node (file or folder)
if (!nodes.ContainsKey(path_part))
nodes.Add(path_part, path_part);
//Go one node deeper
nodes = nodes[path_part].Nodes;
}
}
注-パス区切り文字で始まるパスで使用すると、破損する可能性があります(例:/home/user
)
また、パスの共通部分を削除する(または単一の親ノードを削除する)場合は、前のコードの直後に次のコードブロックを使用します。
//This removes "single" TreeNodes (common paths)
while (treeView1.Nodes.Count == 1)
{
//This "unpacks" child TreeNodes from the only parent TreeNode
for (int i = 0; i < treeView1.Nodes[0].Nodes.Count; i++)
treeView1.Nodes.Add(treeView1.Nodes[0].Nodes[i]);
//This removes parent TreeNode
treeView1.Nodes.RemoveAt(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;
}
コードからASP.NETツリービューを作成するためにかつて使用した非常に古いコードを次に示します(TreeViewのIDが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;
}