Медленный TreeNode с флажками [большое количество] - PullRequest
1 голос
/ 20 августа 2010

Событие AfterCheck элемента управления Tree View проверяет все дочерние узлы под ним и активирует кнопку Run, если что-то проверено.

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 подузлов приведет к зависанию графического интерфейса пользователя примерно на 7секунд.

Мне нужно только один раз вызвать IsANodeChecked (в строке 1351), но я не знаю, как отключить его, пока не будут обработаны все узлы дерева.

И яне хочу, чтобы в моей форме был таймер, посвященный мониторингу этого.

Кто-нибудь видит простое / очевидное решение?

Ответы [ 3 ]

2 голосов
/ 20 августа 2010

Поместите обработчик событий на свои флажки, который включает или отключает 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();
}
1 голос
/ 20 августа 2010

Я иногда использую Timer для обработки таких случаев. Добавьте таймер и настройте обработчик событий Tick на вызов IsANodeChecked и включите / отключите кнопку. Дайте ему короткий интервал (возможно, ~ 100 мс) и оставьте его отключенным. Затем вы вызываете Stop, а затем Start в таймере вашего обработчика событий AfterCheck. Это приведет к перезапуску таймера для каждого вызова AfterCheck, но обработчик события Tick будет вызываться только по истечении определенного времени после вызова Start, что означает, что он не будет вызываться до последний звонок на AfterCheck.

100 мс - это очень долгое время для работы компьютера, но для пользователя оно будет немедленным.

Подобное поведение вы можете увидеть в проводнике Windows. Если вы используете клавиатуру для быстрого перемещения по дереву папок, правая панель с содержимым папки не обновится, если вы не останетесь в папке в дереве на короткое время.

0 голосов
/ 21 августа 2010

Эти идеи были полезны, но я использовал что-то другое, работавшее, добавив одну логическую переменную:

bool _treeNodeFirst = false;

... и событие Before Checked, которое временно изменяет Back Back на элементе управления, чтобы служить в качестве флага для элемента управления, запустившего цепочку событий:

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) запускается только один раз, когда группа узлов выбирается одновременно

Однако мне действительно нравится идея Джимми Хоффа использовать счет. Я, вероятно, добавлю это в мой код.

Спасибо всем! ~ Джо

...