cmbDrives.DataSource = Environment.GetLogicalDrives();
我有这个代码来显示组合框中的所有驱动器,并希望在comboboxselectionchanged
事件上显示treeview
中所有驱动器的相关数据。
我该怎么做呢?
下面的代码通过利用backgroundworker来确保UI在文件夹遍历过程中保持响应,从而实现了您想要的效果。
首先添加一个ComboBox,一个Treeview和一个BackgroundWorker到你的设计图面上。确保使用eventview从Properties窗口为每个控件添加下面代码中使用的事件。确保为BackgroundWorker设置属性WorkerReportsProgress
为true。
首先是ComboBox SelectionIndexChanged事件:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
this.comboBox1.Enabled = false;
this.backgroundWorker1.RunWorkerAsync(comboBox1.SelectedItem.ToString());
}
我们禁用组合框以防止在处理驱动器遍历时选择新值。然后我们启动BackgroundWorker,将SelectedItem传递给它,假设它是一个有效的驱动器。
<<h3>背景工人/h3> DoWork事件接受一个eventargs,它有一个Argument属性,包含我们在调用RunWorkerAsync时提供的值。由于我们现在在一个非UI线程上,我们需要一些技巧来更新UI。后台工作程序可以用它的ReportProgress方法来做这件事。它接受一个整数(通常用于表示我们所走的距离)和一个可选的userstate。我们使用这两个来指示我们所处的状态,并提供一个需要在我们的TreeView上添加或更新的TreeNode。然后调用GetDirectoryNodes
进行目录遍历。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
TreeNode node = new TreeNode(e.Argument.ToString());
backgroundWorker1.ReportProgress(0, node);
GetDirectoryNodes(e.Argument.ToString(), node);
}
ProgressChanged被调用,每次我们有一个TreeNode(或TreeNode的元组),所以我们可以添加节点到TreeView或它的节点之一,而我们在UI线程。ProgressPercentage
不是用来显示我们走了多远,而是用来区分初始状态和遍历状态。
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
switch (e.ProgressPercentage)
{
case 0:
// we have s TreeNode, this is our root.
treeView1.Nodes.Add((TreeNode) e.UserState);
break;
case 1:
// we get a tuple, the parent and it's intended child.
var tup = (Tuple<TreeNode,TreeNode>) e.UserState;
tup.Item1.Nodes.Add(tup.Item2);
break;
default:
break;
}
}
一旦我们完成(即遍历每个文件夹),我们再次启用组合框,以便我们可以选择一个新的驱动器。
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.comboBox1.Enabled = true;
}
驱动器文件夹遍历
要遍历目录树,我使用递归函数(松散地灵感来自Chris Ballard的答案,一旦它有准备添加到TreeView的TreeNode,就调用BackgroundWorkers ReportProgress
方法)。请注意,我是如何使用Tuple作为状态对象,其中包含要添加的Parent和Child,但该特定操作留给UI-Thread上的ProgressChanged事件。
private void GetDirectoryNodes(string path, TreeNode node)
{
try
{
var subDirs = Directory.GetDirectories(path);
foreach (string p in subDirs)
{
var subnode = new TreeNode(p);
backgroundWorker1.ReportProgress(
1,
new Tuple<TreeNode, TreeNode>(
node, subnode
));
GetDirectoryNodes(p, subnode); // recursive!
}
}
catch (Exception exp)
{
var subnode = new TreeNode(path+"\error");
subnode.ToolTipText = exp.Message;
backgroundWorker1.ReportProgress(
1,
new Tuple<TreeNode, TreeNode>(
node, subnode
));
}
}