Ответы на вопрос , который я упомянул в своем комментарии, показывают нам различные способы, как перебирать узлы древовидного представления. Для этого вам понадобится Рекурсивная функция , которая является функцией, которая вызывает себя .
Теперь вернемся к вашему коду. Вам не нужно создавать две функции для проверки и снятия отметки с узлов, а также не использовать foreach для каждого узла, дочернего узла и дочернего узла дочернего узла ... и т. Д. Пожалуйста, попробуйте следующее:
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action == TreeViewAction.Unknown) { return; }
foreach (TreeNode tn in GetNodes(e.Node))
tn.Checked = e.Node.Checked;
}
private static IEnumerable<TreeNode> GetNodes(TreeNode parentNode)
{
foreach (TreeNode tn in parentNode.Nodes)
{
yield return tn;
foreach (TreeNode child in GetNodes(tn))
{
yield return child;
}
}
}
Таким образом, вы можете использовать этот итератор для выполнения других операций с вашими узлами, а не только для их проверки / снятия.
Редактировать
Вы можете увидеть это странное поведение в секундах 7, 10, 15.
Я получил вашу точку зрения.
Такое поведение происходит, когда выслишком быстрый щелчок мышью на узле, поэтому вы фактически делаете щелчок мышью, последовательность двойного щелчка мышьюЭлемент управления древовидного представления по умолчанию не переключает состояние проверки узлов с помощью двойного щелчка мышью, если вы не попросите его сделать это. Как? На этот вопрос уже ответили PhilP в .
- Создайте новый класс, который наследует элемент управления древовидной структуры, и переопределите событие WndProc . следующим образом:
class TreeViewEx : TreeView
{
public TreeViewEx()
{ }
#region This extra to reduce the flickering
private const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44;
private const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45;
private const int TVS_EX_DOUBLEBUFFER = 0x4;
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
protected override void OnHandleCreated(EventArgs e)
{
SendMessage(Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);
base.OnHandleCreated(e);
}
#endregion
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x203 && CheckBoxes)
{
int x = m.LParam.ToInt32() & 0xffff;
int y = (m.LParam.ToInt32() >> 16) & 0xffff;
TreeViewHitTestInfo hitTestInfo = HitTest(x, y);
if (hitTestInfo.Node != null && hitTestInfo.Location == TreeViewHitTestLocations.StateImage)
{
OnBeforeCheck(new TreeViewCancelEventArgs(hitTestInfo.Node, false, TreeViewAction.ByMouse));
hitTestInfo.Node.Checked = !hitTestInfo.Node.Checked;
OnAfterCheck(new TreeViewEventArgs(hitTestInfo.Node, TreeViewAction.ByMouse));
m.Result = IntPtr.Zero;
return;
}
}
base.WndProc(ref m);
}
}
В конструкторе формы, содержащей ваше древовидное представление, измените тип древовидного представления на расширенный, который мы только что создали.
Используйте тот же код для переключения состояния проверки.
Перестройте свой проект.
Этовсе это.
Вот короткая демонстрация. Я щелкаю мышью и дважды щелкаю как сумасшедшая. Однако работает как надо. Надеюсь.
Удачи