问题
Im setting up a new Form and Im having some issuis with the TreeViewNodes checking and uncheking the childs. Its easier to see the problem in this short clip
Normally it works properly but sometimes it gets stuck (I think there is a conflict with selection but Im not sure) and the methods arent applied properly.
I have this methods to check and uncheck the childs:
private void Treeview_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action != TreeViewAction.Unknown)
if (e.Node.Checked)
{
CheckAll(e.Node.Nodes);
}
if (e.Node.Checked == false)
{
Uncheckall(e.Node.Nodes);
}
}
public void Uncheckall(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
node.Checked = false;
foreach (TreeNode node1 in node.Nodes)
{
node1.Checked = false;
foreach (TreeNode node2 in node1.Nodes)
{
node2.Checked = false;
}
}
}
}
public void CheckAll(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
node.Checked = true;
foreach (TreeNode node1 in node.Nodes)
{
node1.Checked = true;
foreach (TreeNode node2 in node1.Nodes)
{
node2.Checked = true;
}
}
}
}
And I have tried to make the selection null:
private void TreeView_Select(object sender, TreeViewEventArgs e)
{
TreeView.SelectedNode = null;
}
But the problem remains. Any ideas? Thanks
回答1:
The answers of the question that I mentioned in my comment shows us different ways regarding how to iterate through TreeView
nodes. To do that, you need a Recursive Function which is a function that calls itself.
Now, back to your code. You don't need to create two functions to check and uncheck the nodes, nor using foreach
for each node, child node, and child node of a child node...etc. Please try the following:
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;
}
}
}
This way, you can use this iterator to do other things to your nodes not only to check/uncheck them.
Edit
You can see this strange behaviour in the seconds 7, 10, 15.
I got your point now.
That behavior occurs when you mouse click too fast on a node so you are actually doing mouse click, mouse double click sequence. The tree view control by default does not toggle the check state of the nodes through the mouse double click unless you tell it to do so. How? Already answered by PhilP in this question.
- Create a new class that inherits the tree view control and override the WndProc event as follow:
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);
}
}
In the designer of the form which contains your
TreeView
, change the type of theTreeView
to the extended one that we just created.Use the same code to toggle the check state.
Rebuild your project.
That's it all.
Here is a quick demo. I'm mouse clicking and double clicking like crazy. However, it works as it should. Hopefully.
Related
◉ CheckBox not work properly when clicked on quickly multiple times
来源:https://stackoverflow.com/questions/58522970/aftercheck-and-afterselect-events-in-treeview-in-windows-forms