1

ツリー ビュー コントロールの AfterCheck イベントは、その下にあるすべての子ノードをチェックし、何かがチェックされている場合は [実行] ボタンを有効にします。

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 行目) を 1 回呼び出すだけで済みますが、すべてのツリー ノードが処理されるまで無効にする方法がわかりません。

そして、これを監視するためのタイマーをフォームに付けたくありません。

単純な/明白な解決策を見ている人はいますか?

4

3 に答える 3

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();
}
于 2010-08-20T19:34:56.330 に答える
1

Timerそのような場合を処理するために a を使用することがあります。タイマーを追加し、ボタンを呼び出して有効/無効にするTickイベント ハンドラーを設定します。IsANodeChecked短い間隔 (おそらく ~100 ミリ秒) を与え、無効のままにします。Stop次に、イベント ハンドラーStartでタイマーを呼び出します。AfterCheckこれにより、 への呼び出しごとにタイマーが再起動されますAfterCheckが、Tickイベント ハンドラーは、呼び出しから一定の時間が経過した場合にのみ呼び出されます。つまり、イベント ハンドラーはStart、 への最後の呼び出しの後まで呼び出されませんAfterCheck

100 ミリ秒は、コンピューターが動作するのに非常に長い時間ですが、ユーザーにはすぐに見えます。

Windows エクスプローラーでも同様の動作を確認できます。キーボードを使用してフォルダ ツリー内をすばやく移動すると、ツリー内のフォルダにしばらく留まらない限り、右側のペインのフォルダ コンテンツが更新されません。

于 2010-08-20T19:33:34.727 に答える
0

これらのアイデアは役に立ちますが、単一のブール変数を追加することで機能する別のものを使用しました。

bool _treeNodeFirst = false;

...そして、コントロールの Back Color を一時的に変更して、一連のイベントを開始したコントロールのフラグとして機能する Before Checked イベント:

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)これは、ノードのグループが一度に選択されたときに一度だけ実行されるようにするための最良の方法のようです (私が今見ることができる) 。

ただし、カウントを使用するというジミー・ホッファのアイデアは本当に気に入っています。私はおそらくそれを私のコードに追加します。

ありがとうございます!〜ジョー

于 2010-08-20T21:22:46.813 に答える