问题
I want to make a treeview that shows all folders on the system, and only shows music files, such as .mp3 .aiff .wav etc.
I remember reading that I need to use a recursive function or something along those lines.
回答1:
Usually most computers have thousands of folders and hundreds of thousands of files, so displaying all of them in a TreeView recursively with be very slow and consume a lot of memory, view my answer in this question, citing my answer with some modifications when can get a pretty usable GUI:
// Handle the BeforeExpand event
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (e.Node.Tag != null) {
AddDirectoriesAndMusicFiles(e.Node, (string)e.Node.Tag);
}
}
private void AddDirectoriesAndMusicFiles(TreeNode node, string path)
{
node.Nodes.Clear(); // clear dummy node if exists
try {
DirectoryInfo currentDir = new DirectoryInfo(path);
DirectoryInfo[] subdirs = currentDir.GetDirectories();
foreach (DirectoryInfo subdir in subdirs) {
TreeNode child = new TreeNode(subdir.Name);
child.Tag = subdir.FullName; // save full path in tag
// TODO: Use some image for the node to show its a music file
child.Nodes.Add(new TreeNode()); // add dummy node to allow expansion
node.Nodes.Add(child);
}
List<FileInfo> files = new List<FileInfo>();
files.AddRange(currentDir.GetFiles("*.mp3"));
files.AddRange(currentDir.GetFiles("*.aiff"));
files.AddRange(currentDir.GetFiles("*.wav")); // etc
foreach (FileInfo file in files) {
TreeNode child = new TreeNode(file.Name);
// TODO: Use some image for the node to show its a music file
child.Tag = file; // save full path for later use
node.Nodes.Add(child);
}
} catch { // try to handle use each exception separately
} finally {
node.Tag = null; // clear tag
}
}
private void MainForm_Load(object sender, EventArgs e)
{
foreach (DriveInfo d in DriveInfo.GetDrives()) {
TreeNode root = new TreeNode(d.Name);
root.Tag = d.Name; // for later reference
// TODO: Use Drive image for node
root.Nodes.Add(new TreeNode()); // add dummy node to allow expansion
treeView1.Nodes.Add(root);
}
}
回答2:
Recursively searching all drives for particular files is not going to work well. It will take about a minute to do so with today's large drives.
One standard trick, used by Windows Explorer, is to only list the top level directories and files. It puts a dummy node in a directory node. When the user opens the node (BeforeExpand event), it searches only that directory and replaces the dummy node with the directories and files found it that directory. Again putting a dummy node in the directories. Etcetera.
You can see this at work by adding an empty subdirectory. The directory node will be shown with the + glyph. When you open it, Explorer discovers that there are no directory or files to be listed and deletes the dummy node. The + glyph disappears.
This is very fast, listing the content of a single directory takes well less than a second. There's a problem however using this approach in your case. The odds that a directory contains a suitable music file are small. The user will constantly be frustrated by finding out that the navigating through a set of subdirectories produces nothing.
That's why Windows has a dedicated place to store specific media files. My Music in this case. Use Environment.GetFolderPath(Environment.SpecialFolder.MyMusic) to find it. Iterating it should not take long.
来源:https://stackoverflow.com/questions/2263013/recursive-directory-listing-using-winforms-treeview