如何从Windows目录列表文件递归生成C# TreeView?
Hey there! Let's break down how to turn that Windows directory listing into a fully functional TreeView in C#. First, let's recap the directory structure you're working with (formatted as code for clarity):
Volume in drive D is DATA Volume Serial Number is A4EC-104D Directory of D:\Studies\Projects\test 14/07/2019 08:09 PM <DIR> . 14/07/2019 08:09 PM <DIR> .. 14/07/2019 08:08 PM <DIR> Test1 0 File(s) 0 bytes Directory of D:\Studies\Projects\test\Test1 14/07/2019 08:08 PM <DIR> . 14/07/2019 08:08 PM <DIR> .. 14/07/2019 08:08 PM <DIR> Test2 14/07/2019 08:08 PM <DIR> Test3 0 File(s) 0 bytes Directory of D:\Studies\Projects\test\Test1\Test2 14/07/2019 08:08 PM <DIR> . 14/07/2019 08:08 PM <DIR> .. 14/07/2019 08:08 PM <DIR> Test4 0 File(s) 0 bytes Directory of D:\Studies\Projects\test\Test1\Test2\Test4 14/07/2019 08:08 PM <DIR> . 14/07/2019 08:08 PM <DIR> .. 14/07/2019 08:08 PM 0 testfile.txt 1 File(s) 0 bytes Directory of D:\Studies\Projects\test\Test1\Test3 14/07/2019 08:08 PM <DIR> . 14/07/2019 08:08 PM <DIR> .. 14/07/2019 08:08 PM 0 file2.txt 1 File(s) 0 bytes Total Files Listed: 2 File(s) 0 bytes 14 Dir(s) 372,031,488,000 bytes free
You'll need to complete three key steps, and yes, recursion is absolutely the right tool here—it's perfect for handling nested directory structures where each level follows the same logic.
1. Parse the Directory Listing File
First, we need to read the text file and extract meaningful data: directory paths, subdirectories, and files. We'll use regex and string manipulation to filter out system lines (like . and ..) and capture the important details.
2. Build a Hierarchical Data Structure
We'll create a simple class to represent each node (directory or file), then organize these nodes into a tree where each directory contains its child directories and files.
3. Recursively Populate the TreeView
Once we have our tree structure, we'll write a recursive function to traverse it and add nodes to the WinForms TreeView control. Each directory node will trigger the same function to add its own children.
Let's dive into the code. First, add these using directives at the top of your form class:
using System.IO; using System.Text.RegularExpressions; using System.Collections.Generic; using System.Linq;
Step 1: Define a Node Class
This class will hold all the info we need for each directory/file:
public class TreeNodeData { public string Name { get; set; } public string FullPath { get; set; } public bool IsDirectory { get; set; } public List<TreeNodeData> Children { get; set; } = new List<TreeNodeData>(); }
Step 2: Parse the File and Build the Hierarchy
This method reads the file, extracts nodes, and organizes them into a tree:
private List<TreeNodeData> ParseAndBuildHierarchy(string filePath) { var allNodes = new List<TreeNodeData>(); string currentDir = string.Empty; foreach (var line in File.ReadAllLines(filePath)) { // Match lines that start with "Directory of " to get the current directory path var dirMatch = Regex.Match(line, @"Directory of (.*)"); if (dirMatch.Success) { currentDir = dirMatch.Groups[1].Value; // Add the current directory as a node if it doesn't exist yet if (!allNodes.Any(n => n.FullPath == currentDir)) { allNodes.Add(new TreeNodeData { Name = Path.GetFileName(currentDir), FullPath = currentDir, IsDirectory = true }); } continue; } // Skip system entries, empty lines, and summary lines if (line.Contains("<DIR> .") || line.Contains("<DIR> ..") || string.IsNullOrWhiteSpace(line) || line.StartsWith("Total Files Listed:")) continue; // Check if this line is a subdirectory if (line.Contains("<DIR>")) { var dirName = line.Substring(39).Trim(); var fullPath = Path.Combine(currentDir, dirName); allNodes.Add(new TreeNodeData { Name = dirName, FullPath = fullPath, IsDirectory = true }); } else { // It's a file var fileName = line.Substring(39).Trim(); var fullPath = Path.Combine(currentDir, fileName); allNodes.Add(new TreeNodeData { Name = fileName, FullPath = fullPath, IsDirectory = false }); } } // Now organize nodes into parent-child relationships var nodeLookup = allNodes.ToDictionary(n => n.FullPath); var rootNodes = new List<TreeNodeData>(); foreach (var node in allNodes) { if (node.IsDirectory) { var parentPath = Path.GetDirectoryName(node.FullPath); if (nodeLookup.TryGetValue(parentPath, out var parentNode)) { parentNode.Children.Add(node); } else { // This is a root directory (like D:\Studies\Projects\test) rootNodes.Add(node); } } else { // Add files to their parent directory var parentPath = Path.GetDirectoryName(node.FullPath); if (nodeLookup.TryGetValue(parentPath, out var parentNode)) { parentNode.Children.Add(node); } } } return rootNodes; }
Step 3: Recursively Populate the TreeView
These methods take our hierarchical data and add it to the TreeView control:
private void PopulateTreeView(TreeView targetTreeView, List<TreeNodeData> rootNodes) { targetTreeView.Nodes.Clear(); foreach (var rootNode in rootNodes) { var treeNode = CreateTreeViewNode(rootNode); targetTreeView.Nodes.Add(treeNode); // Recursively add child nodes AddChildNodes(treeNode, rootNode.Children); } } private void AddChildNodes(TreeNode parentTreeNode, List<TreeNodeData> childDataNodes) { foreach (var childData in childDataNodes) { var childTreeNode = CreateTreeViewNode(childData); parentTreeNode.Nodes.Add(childTreeNode); // If it's a directory, keep recursing to add its children if (childData.IsDirectory) { AddChildNodes(childTreeNode, childData.Children); } } } private TreeNode CreateTreeViewNode(TreeNodeData data) { var node = new TreeNode(data.Name); // Store the full path in the Tag property for later use (e.g., opening the file) node.Tag = data.FullPath; // Optional: Set different icons for directories/files (add an ImageList to your form first) // node.ImageIndex = data.IsDirectory ? 0 : 1; // node.SelectedImageIndex = data.IsDirectory ? 0 : 1; return node; }
Step 4: Use the Code in Your Form
Call these methods from your form's Load event (replace the file path with your actual file location):
private void MainForm_Load(object sender, EventArgs e) { string listingFilePath = @"D:\path\to\your\directory_list.txt"; var rootNodes = ParseAndBuildHierarchy(listingFilePath); PopulateTreeView(treeView1, rootNodes); }
- The line
line.Substring(39)works for your specific directory listing format. If yourdiroutput has different spacing, you might want to use a regex to extract the name instead (e.g.,Regex.Match(line, @"\s+(.*)$").Groups[1].Value). - To add icons, add an
ImageListcontrol to your form, load directory and file icons into it, then settreeView1.ImageList = yourImageList;. - Recursion makes this code clean and maintainable—instead of writing nested loops for each possible directory level, we reuse the same logic for every node.
内容的提问来源于stack exchange,提问作者shriram pugazendhi

