2016-01-20 128 views
2

我有一个简单的WinForms应用程序与TreeView控件。 我正在尝试创建ExpandAll函数。它调用获取选定节点并运行递归函数WinForms:导航TreeView在BackgroundWorker线程

private void expandNode2(TreeNode tn) 
{ 
    if (tn == null) return; 

    tn.TreeView.BeginUpdate(); 
    Application.DoEvents(); 
    tn.Expand(); 
    tn.TreeView.EndUpdate(); 
    foreach (TreeNode tnChild in tn.Nodes) 
    { 
     expandNode2(tnChild); 
    } 
} 

如果树很大,表单被冻结。如何在backgroundworker线程中展开树?当我调用这个函数时,我收到了交叉线程错误。

回答

0

由于主线程拥有treeView,您需要调用invoke来更新树。但是,这会将节点的扩展重新放回主线程,从而锁定您的用户界面。

你可以克隆你的根节点,然后将其传递给后台工作者(bw) 展开该节点及其子节点然后将其传回并将你的root =设置为bw结果(可以在bw中完成方法)。这都将移动扩展到体重,但可能是昂贵的资源明智的,因为我们有克隆第一

private void btnExpandR_Click(object sender, EventArgs e) 
    { 
     BackgroundWorker bw = new BackgroundWorker(); 
     TreeNode tempnode = treeView.Nodes[0].Clone() as TreeNode; 
     bw.DoWork += bw_DoWork; 
     bw.RunWorkerCompleted += NodeCopy; 
     bw.RunWorkerAsync(tempnode); 
    } 

    private void NodeCopy(object sender, RunWorkerCompletedEventArgs e) 
    { 
     treeView.Nodes[0] = e.Result as TreeNode; 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     TreeNode tempNode = e.Argument as TreeNode; 
     Exp(tempNode); 
     e.Result = tempNode; 
    } 

    private void Exp(TreeNode tn) 
    { 
     tn.Expand(); 

     foreach(TreeNode t in tn.Nodes) 
     { 
      if(t.Nodes.Count > 0) 
      { 
       exp(t); 
      } 
     } 
    } 

您的节点时,您也可以只用

private void Exp(TreeNode tn) 
    { 
     tn.ExpandAll(); 
    } 
+0

这似乎不错扩大,我会尝试, 谢谢。我知道我可以使用expandall,但这里有另一个想法:树通过WCF从db中填充。我想要有测试应用程序来为WCF和db创建加载。我点击按钮,树逐级扩展。这样我可以在应用程序或N个应用程序中运行N个表单,并且它们将创建自动加载。 – Oleg

+0

在这种情况下,用户看到扩展的树,但没有看到进度,逐步扩大。 – Oleg

+0

在这种情况下,我认为你有点后退。而不是构建树,然后尝试逐层扩展它。为什么在从db中加载节点时不能构建具有扩展节点的树?只要我尝试使用treeview.Nodes.Find复制比treeView.Nodes [0]更深的节点,树就停止了扩展。我可以从一棵已经填充的树中一次性扩展一个节点的唯一方法是删除已完成的bw中的节点,并重新添加该节点的扩展副本。 – Krill