2016-01-20 75 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