我在网上找到了这个代码。它可以工作,但由于某种原因,它会加载文件目录两次。
namespace DockSample.Controls
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using Microsoft.VisualBasic.FileIO;
using DockSample;
//TODO: Add options for filtering by robot
public class SolutionExplorer : TreeView
{
public SolutionExplorer()
{
this.BeforeExpand += customBeforeExpand;
this.Nodes.Clear();
CreateTree(this);
}
private bool CreateTree(TreeView treeView)
{
bool returnValue = false;
try
{
// Create Desktop
TreeNode desktop = new TreeNode();
// desktop.Text = "Desktop";
// desktop.Tag = "Desktop";
// desktop.Nodes.Add("");
// treeView.Nodes.Add(desktop);
// Get driveInfo
foreach (DriveInfo drv in DriveInfo.GetDrives())
{
TreeNode fChild = new TreeNode();
if (drv.DriveType == DriveType.CDRom)
{
fChild.ImageIndex = 1;
fChild.SelectedImageIndex = 1;
}
else if (drv.DriveType == DriveType.Fixed)
{
fChild.ImageIndex = 0;
fChild.SelectedImageIndex = 0;
}
fChild.Text = drv.Name;
fChild.Nodes.Add("");
treeView.Nodes.Add(fChild);
returnValue = true;
}
}
catch
{
returnValue = false;
}
return returnValue;
}
/* Method :EnumerateDirectory
* Author : Chandana Subasinghe
* Date : 10/03/2006
* Discription : This is use to Enumerate directories and files
*
*/
public TreeNode EnumerateDirectory(TreeNode parentNode, List<string> thisFilter)
{
try
{
DirectoryInfo rootDir;
// To fill Desktop
Char[] arr = { '\\' };
string[] nameList = parentNode.FullPath.Split(arr);
string path = "";
if (nameList.GetValue(0).ToString() == "Desktop")
{
path = SpecialDirectories.Desktop + "\\";
for (int i = 1; i < nameList.Length; i++)
{
path = path + nameList[i] + "\\";
}
rootDir = new DirectoryInfo(path);
}
// for other Directories
else
{
rootDir = new DirectoryInfo(parentNode.FullPath + "\\");
}
parentNode.Nodes[0].Remove();
foreach (DirectoryInfo dir in rootDir.GetDirectories())
{
TreeNode node = new TreeNode();
node.Text = dir.Name;
node.Nodes.Add("");
parentNode.Nodes.Add(node);
}
//Fill files
foreach (FileInfo file in rootDir.GetFiles())
{
if (isValidFilter(getExtention(file.Name)))
{
TreeNode node = new TreeNode();
node.Text = file.Name;
node.ImageIndex = 2;
node.SelectedImageIndex = 2;
parentNode.Nodes.Add(node);
}
}
}
catch
{
}
return parentNode;
}
private bool isValidFilter(string ext)
{
bool result = false;
foreach(string s in filter)
{
if (ext == s)
result = true;
}
return result;
}
private string getExtention(string filename)
{
return filename.Substring(filename.IndexOf("."));
}
private void customBeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (e.Node.Nodes[0].Text == "")
{
TreeNode node = this.EnumerateDirectory(e.Node,filter);
}
}
private List<string> filter = new List<string>();
public List<string> Filter
{
get { return filter; }
set { filter = value; }
}
private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);
}
}
}
答案 0 :(得分:2)
控件的构造函数在设计时和运行时都运行。因此,只要您将控件放在窗体上,它就会填充树视图。问题是,节点将被序列化为InitializeComponent()。看看你的表单的Designer.cs文件,你会发现它们在那里。运行表单时,构造函数再次运行,使列表加倍。
您需要阻止构造函数在设计时添加节点。这有点难以做到,您通常使用DesignMode属性,但在构造函数中它尚未设置为true。这样做是这样的:
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
if (!DesignMode && treeView.Nodes.Count == 0) {
CreateTree(this);
}
}
或者通过添加在窗体的构造函数或OnLoad方法中调用的公共方法来显式地执行此操作。这是明智的,您可能想要捕获异常。修补文件系统时总是有可能。