Notifications
Clear all

[Closed] dotNet treeview checked/unchecked items

I’ve created a TreeView that has check boxes for
filtering. When a parent node is checked, all of its
children should become checked and when it is unchecked
its children should be unchecked. This works fine; I’m
using the AfterCheck event.

The problem is that if a child becomes unchecked then its
parent should also become unchecked (but not its sibling
nodes). Right now, this is creating a loop in my code
because when the uncheck event fires (with the intent to
only uncheck the parent) then the parent tries to uncheck
all of its children and it gets confused, so an exception
is thrown.

I’ve thought about trying to create a click event that
somehow detects if a TreeView checkbox was checked and if
so, which one, so that I can distinguish between a user
checking and programmatically checking a checkbox, but I’m
not quite sure how this would work.

Do you have a solution?

Thanks!

6 Replies

Hm-m… Really it is such difficult question and nobody can help me?
Any help, please.

why not just use a good old fasioned flag ?

4 Replies
(@3dzver)
Joined: 2 years ago

Posts: 0

Sorry, but I have not understood your question. What is “old fasioned flag”?

(@ypuech)
Joined: 2 years ago

Posts: 0

For example, use a boolean flag to stop the infinite loop when you’ve already updated the parent node checked state.

(@3dzver)
Joined: 2 years ago

Posts: 0

Thanks, ypuech, for your answer. But I had in view of little bit another. For example, earlier in ActiveX I used such code for this purpose:


 on treeView NodeCheck checkedNode do (
 		ToggleNode checkedNode checkedNode.Checked
 	)
 
 function ToggleNode node checkedState = (
 
 if (node.Child != undefined) then (
 		if (node.Child.Checked != checkedState) then (
 			ToggleNode node.Child checkedState
 		)
 		local chNode = node.Child.Checked
 		local nextNode = node.Child.Next
 
 		while (nextNode != undefined) do (
 			if (nextNode.Checked != checkedState) then (
 				ToggleNode nextNode checkedState
 			)
 			chNode = nextNode.Checked
 			nextNode = nextNode.Next
 		)
 		if (chNode != true) then (
 				node.Expanded = false
 			)
 	)
 )
 

How now it can be realized in dotNet? In fact there are no such parameters as Child and Child.Next…

Ок. I have found a provisional code of realization of similar operation in C ++, but I do not know as it to make in maxscript:


 TreeNode userInvoke = null;
 
 private void treeView_AfterCheck(object sender, TreeViewEventArgs e)
 {
 	if(e.Action == TreeViewAction.ByMouse)
 		userInvoke = e.Node;
 	
 	if( IsDescendent(userInvoke, e.Node))
 	{
 		foreach(TreeNode tn in e.Node.Nodes)
 			tn.Checked = e.Node.Checked;
 	}
 
 	if( IsDescendent(e.Node, userInvoke))
 	{
 		TreeNode pn = e.Node.Parent;
 		if(pn == null)
 			return;
 
 		bool bAllChecked = true;
 		foreach(TreeNode tn in pn.Nodes)
 			bAllChecked = bAllChecked && tn.Checked;
 	
 		if(pn.Checked && !bAllChecked)
 			pn.Checked = false;
 
 		if(!pn.Checked && bAllChecked)
 			pn.Checked = true;
 	}
 
 }
 
 bool IsDescendent(TreeNode parent, TreeNode desc)
 {
 return desc.FullPath.IndexOf(parent.FullPath) == 0;		
 }
 

Thanks for any help.

(sorry for bad english)

(@ypuech)
Joined: 2 years ago

Posts: 0

There are Nodes property that contains all the child nodes of a TreeNode. And you can get the next node at the same level just using NextNode property.

Here is the code example:

(
 	rollout WorldTreeViewDemoRollout "World Demo" width:150 height:200
 	(
 		local childPropagate = true
 		local parentPropagate = true
 		
 		-- Updates all child tree nodes recursively
 		fn CheckAllChildNodes treeNode checkNode =
 		(
 			if parentPropagate and childPropagate then
 			(
 				childNodesCount = treeNode.Nodes.Count
 				if childNodesCount > 0 then
 				(
 					-- For each child nodes, check childs etc.
 					for idxChildNode = 0 to childNodesCount-1 do
 					(
 						childNode = treeNode.Nodes.Item[idxChildNode]
 						childNode.Checked = checkNode
 						-- Recursively propagate to child nodes
 						CheckAllChildNodes childNode checkNode
 					)
 				)
 			)
 		)
 		
 		-- Updates all parent tree nodes recursively
 		fn CheckAllParentNodes treeNode checkNode =
 		(
 			parentNode = treeNode.Parent
 			if parentNode != undefined then
 			(
 				if checkNode then
 				(
 					parentNodeChildCount = parentNode.Nodes.Count
 					if parentNodeChildCount > 0 then
 					(
 						-- Get check state of the child nodes
 						idxChildNode = 0
 						checkChildNode = true
 						-- Checked state of parent is true only when all child nodes are checked
 						while checkNode and idxChildNode < parentNodeChildCount do
 						(
 							childNode = parentNode.Nodes.Item[idxChildNode]
 							checkChildNode = childNode.Checked
 							idxChildNode += 1
 						)
 						
 						checkNode = checkChildNode
 					)
 				)
 				parentNode.Checked = checkNode
 				-- Recursively propagate to parent nodes
 				CheckAllParentNodes parentNode checkNode
 			)
 		)
 
 		dotNetControl treeView "System.Windows.Forms.TreeView" pos:[0,0] width:150 height:200 align:#center
 		
 		on WorldTreeViewDemoRollout open do
 		(
 			treeView.CheckBoxes = True
 			
 			-- Create TreeView nodes
 			nodeAfrica = dotNetObject "System.Windows.Forms.TreeNode" "Africa"
 			nodeAmerica = dotNetObject "System.Windows.Forms.TreeNode" "America"
 			nodeEurope = dotNetObject "System.Windows.Forms.TreeNode" "Europe"
 			nodeFrance = dotNetObject "System.Windows.Forms.TreeNode" "France"
 			nodeItaly = dotNetObject "System.Windows.Forms.TreeNode" "Italy"
 			nodeEurope.Nodes.Add nodeFrance
 			nodeEurope.Nodes.Add nodeItaly
 			
 			-- Create World node
 			nodeWorlds = dotNetObject "System.Windows.Forms.TreeNode" "World"
 			-- Add childs
 			nodeWorlds.Nodes.Add nodeAfrica
 			nodeWorlds.Nodes.Add nodeAmerica
 			nodeWorlds.Nodes.Add nodeEurope
 			
 			-- Add World root node
 			treeView.Nodes.Add nodeWorlds
 			-- Expand all nodes in the TreeView
 			treeView.ExpandAll()
 		)
 		
 		on treeView AfterCheck treeViewArgs do
 		(
 			TreeViewAction = dotNetClass "System.Windows.Forms.TreeViewAction"
 			
 			-- Get event args
 			treeViewNode = treeViewArgs.Node
 			nodeChecked = treeViewArgs.Node.Checked
 			
 			if treeViewArgs.Action != TreeViewAction.Unknown then
 			(
 				-- User interaction : ok to propagate to childs and parents
 				childPropagate = true
 				parentPropagate = true
 			)
 			
 			CheckAllChildNodes treeViewNode nodeChecked
 			
 			if not nodeChecked then
 			(
 				if treeViewArgs.Action != TreeViewAction.Unknown then
 				(
 					-- User interaction : ok to propagate to parents
 					parentPropagate = true
 				)
 				else
 				(
 					parentPropagate = false
 				)
 				
 				-- Never propagate to childs when checking parents nodes
 				childPropagate = false
 			
 				CheckAllParentNodes treeViewNode nodeChecked
 			)
 			else
 			(
 				-- Todo: check parent item only when all its childs are also checked
 				--	   implemented in CheckAllParentNodes() but how to setup the flags ?
 			)
 		)
 	)
 	
 	try(destroyDialog WorldTreeViewDemoRollout)catch()
 	createDialog WorldTreeViewDemoRollout
 )

It works great but there’s one case it can’t handle : it can’t check a parent item when all its child nodes are checked. There’s an infinite loop and I don’t know how to setup the boolean flags. I’ll try to resolve that later.