2010-08-20 51 views
1

樹視圖控件的AfterCheck事件檢查它下面的所有子節點,並啓用運行按鈕(如果選中了某項)。帶有複選框的慢TreeNode [大數量]

1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) { 
1347 if (!e.Node.Checked) return; 
1348 foreach (TreeNode sub in e.Node.Nodes) { 
1349  sub.Checked = e.Node.Checked; 
1350 } 
1351 RunButton.Enabled = IsANodeChecked(); 
1352 } 

1429 static bool IsANodeChecked(TreeNode node) { 
1430 if (node.Checked) return true; 
1431 foreach (TreeNode sub in node.Nodes) { 
1432  if (IsANodeChecked(sub)) { 
1433  return true; 
1434  } 
1435 } 
1436 return false; 
1437 } 

當有4881個子節點時檢查根節點會掛起GUI大約7秒鐘。

我只需要調用IsANodeChecked(在1351行)一次,但我不知道如何禁用它,直到所有的樹節點都被處理完畢。

而且我不想在我的表單上專門用於監視此計時器。

有沒有人看到一個簡單/明顯的解決方案?

+0

您的代碼無法編譯。 – 2010-08-20 19:35:11

回答

0

這些想法,其中有幫助的,但我用不同的東西奏效加入一個布爾變量:

bool _treeNodeFirst = false;

...和臨時修改背景色的控制之前檢查事件作爲啓動該控制標誌e通風口:

1273 void TreeNode_BeforeCheck(object sender, TreeViewCancelEventArgs e) { 
1274 if (!_treeNodeFirst) { 
1275  _treeNodeFirst = true; 
1276  e.Node.BackColor = Color.Silver; 
1277 } 
1278 } 

1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) { 
1347 if (e.Node.Checked) { 
1348  foreach (TreeNode sub in e.Node.Nodes) { 
1349  sub.Checked = e.Node.Checked; 
1350  } 
1351 } 
1352 if (e.Node.BackColor == Color.Silver) { 
1353  e.Node.BackColor = Color.Empty; 
1354  RunButton.Enabled = IsANodeChecked(); 
1355  _treeNodeFirst = false; 
1356 } 
1357 } 

1429 static bool IsANodeChecked(TreeNode node) { 
1430 if (node.Checked) return true; 
1431 foreach (TreeNode sub in node.Nodes) { 
1432  if (IsANodeChecked(sub)) { 
1433  return true; 
1434  } 
1435 } 
1436 return false; 
1437 } 

這似乎是最好的方式(即我可以看到現在),以確保IsANodeChecked(TreeNode)當選擇一次性全部一組節點只運行一次。

不過,我確實很喜歡Jimmy Hoffa關於使用count的想法。我可能會添加到我的代碼。

謝謝大家! 〜Joe

1

我有時使用Timer來處理這種情況。添加一個計時器並設置Tick事件處理程序以調用IsANodeChecked並啓用/禁用該按鈕。給它一個很短的時間間隔(也許〜100 ms),並將其禁用。然後,您在AfterCheck事件處理程序中的計時器上撥打Stop,然後撥打Start。這將導致每次調用AfterCheck時重新啓動計時器,但只有在Start調用之後經過了一段時間後纔會調用Tick事件處理程序,這意味着直到最後一次調用AfterCheck後纔會調用該事件處理程序。

100 ms是一個非常長時間的計算機工作,但似乎立即爲用戶。

您可以在Windows資源管理器中看到類似的行爲。如果您使用鍵盤快速瀏覽文件夾樹中的文件夾,則右側窗格中的文件夾內容將不會更新,除非您暫時停留在樹中的文件夾中。

+0

如果沒有更好的東西出現,我可能不得不在這個應用程序中實現另一個計時器。不過,我寧可不要。 – jp2code 2010-08-20 19:39:33

+0

@ jp2code:如果應用程序已經定時器激烈,我看到你的不情願。我傾向於避免他們,併爲那些特殊場合保存他們,當他們真的會幫助我。 – 2010-08-20 19:41:41

2

將一個事件處理程序放在您的複選框中,該複選框啓用或禁用RunButton,而不是讓它遍歷整個事物來查找。

當複選框首先被選中時,將複選框添加到選中的複選框列表中,以便在選中的複選框列表爲空之前不會禁用RunButton。從當它選中列表等

這裏刪除它的那種我會怎麼寫出來,這只是即興發揮很抱歉,如果我錯過了什麼:

private int _checkedCheckboxes; 

void AddCheckBox() 
{ 
    if (_checkedCheckBoxes++ == 1) RunButton.Enabled = true; 
} 

void RemoveCheckBox() 
{ 
    if (_checkedCheckBoxes-- == 0) RunButton.Enabled = false; 
} 

void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) 
{ 
    if (e.Node.Checked) 
    { 
     AddCheckBox(); 
     return; 
    } 

    RemoveCheckBox(); 
} 
+0

樹節點是根據數據庫中的型號(從序列號)手動創建的。你是說爲每個手動創建的節點創建一個新事件? (比如5000個事件)如果檢查根節點並且所有5000個子節點都立即啓動,那麼這將如何比我現在做的更好?你的想法需要一些時間來設計,所以我想在承諾之前瞭解更多。 – jp2code 2010-08-20 19:44:10