check parent node if all child are checked C# asp.net - c#

I have a custom tree view inherited from asp.net tree view control. with nth level parent- child relationship. based on some calculation I have checked child node. I want parent node should be checked if all the child node are checked. As I am checking child nodes on based some calculation so I can't use after check event.
can some one provide me C# code for that?
private TreeNode _parentNode;
private void CheckedParent(TreeNodeCollection nodeCollection)
{
foreach (TreeNode node in nodeCollection)
{
if (node.ChildNodes.Count > 0)
{
_parentNode = node;
CheckedParent(node.ChildNodes);
}
else
{
bool allChildChecked = true
foreach (TreeNode childNode in nodeCollection)
{
if (!childNode.Checked)
{
allChildChecked = false;
}
}
}
}
if (allChildChecked )
{
_parentNode.Checked = true;
_isAllChildChecked = false;
}
}

This method will return true if all child nodes are checked; otherwise it will return false
private bool AllChildChecked(TreeNode currentNode)
{
bool res = true;
foreach (TreeNode node in currentNode.ChildNodes)
{
res = node.Checked;
if (!res) break;
res = this.AllChildChecked(node);
if (!res) break;
}
return res;
}

Related

How to iterate all child properties recursively while setting values

I have a tree view class.
public class TreeNode
{
public int Id {get;set;}
public HashSet<TreeNode> ChildNodes {get;set;}
public TreeNode ParentNode {get;set;}
public bool IsExpanded {get;set;}
}
All tree items have IsExpanded = false by default.
When I get the leaf node, I need to expand the node and all its parent nodes, all the way up to the root node.
This is what I have tried so far:
//
// This method will return all Ids for the node and all its parent nodes.
//
private IEnumerable<int> YieldIdsRecursively(TreeNode node)
{
yield return node.Id;
if (node.ParentNode is not null)
{
foreach (int id in YieldIdsRecursively(node.ParentNode))
{
yield return id;
}
}
}
//
// I wanted to use the ref modifier to set the Id property of each node.
// However, properties are not supported by the ref modifier in c#
//
private void ExpandNodesRecursively(IEnumerable<int> ids, ref HashSet<TreeNode> nodes)
{
foreach(var node in nodes)
{
if(ids.Contains(node))
{
node.IsExpanded = true;
}
if((node.ChildNodes?.Count ?? 0) > 0)
{
//
// This is where the error pops
//
ExpandNodesRecursively(ids, node.ChildNodes);
}
}
}
Any advises would be greatly appreciated!
Well, I think it's easier to return TreeNode itself instead of its Id:
private IEnumerable<TreeNode> ThisAndAllParents() {
for (TreeNode current = this; current != null; current = current.ParentNode)
yield return current;
}
then ExpandNodesRecursively can be something like this:
private void ExpandNodesRecursively() {
foreach (TreeNode node in ThisAndAllParents())
node.IsExpanded = true;
}

Binary Search Tree "stack" explanation

I have a very simple implemention of BST in C#. The code:
class Node
{
public int? value;
public Node parent;
public Node left;
public Node right;
public Node(int? value, Node parent = null)
{
this.value = value;
this.parent = parent;
}
}
class BST
{
public Node root;
public List<Node> tree = new List<Node>();
public BST(int? value = null)
{
if (value != null)
{
this.root = new Node(value);
this.tree.Add(this.root);
}
}
public Node insert(int value)
{
Node node = this.root;
if (node == null)
{
this.root = new Node(value);
this.tree.Add(this.root);
return this.root;
}
while (true)
{
if (value > node.value)
{
if (node.right != null)
{
node = node.right;
}
else
{
node.right = new Node(value, node);
node = node.right;
break;
}
}
else if (value < node.value)
{
if (node.left != null)
{
node = node.left;
}
else
{
node.left = new Node(value, node);
node = node.left;
break;
}
}
else
{
break;
}
}
return node;
}
}
class Program
{
static void Main()
{
BST superTree = new BST(15);
superTree.insert(14);
superTree.insert(25);
superTree.insert(2);
}
}
My Question is regarding the "Insert" method of the BST class.
How exactly its "return" work when I just call it in the main method?
How does it know to put that "node" on the "left"? I am not referencing "root.left" anywhere but somehow it gets properly inserted.
I realized at some point that some kind of recursion occurs there, but its been like 6 hours and I still can't understand how this method properly works.
I appreaciate any explanation of that "insert" method.Thanks.
Node node = this.root;
Your code always starts with the root, because of this line. It's only after node is no longer null that node be re-assigned to something other than root. The rest of the code works on node.left, but because your code begins with root as above, node.left is actually referencing root at the start.

Trying to remove a node and save it again c#

I have a program, and i want to remove a node from the tree. Ok, i can remove, but when i want to save it again it shows me a error.
public void InsertNode(string value)
{
root = InsertNode(value, root);
}
private Node InsertNode(string value, Node node)
{
if (node == null)
{
node = new Node(value, null, null);
}
else
{
if (node.value.CompareTo(value) > 0) ---- The error is in this line
{
node.lChild = InsertNode(value, node.lChild);
}
else
{
node.rChild = InsertNode(value, node.rChild);
}
}
return node;
}

How to evaluate expression tree with logical operators in C#

I have a tree structure with leaf nodes containing expressions, which are asserted to be True or False , connected by Logical (AND/OR) conditions. I am looking for an algorithm/solution to evaluate the tree by Depth-first-search, based on logical-operators
If the parent node is an AND then no further traversal to sibling is required if the current node is evaluated as false. (also if the current node is TRUE then no further sibling to be visited if the parent node is an OR) - This would optimize the evaluation.I am just curious to know if there is a solution/code already there, rather than reinventing it.
public class TreeNode<T>
{
private readonly T _value;
private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();
public TreeNode(T value)
{
_value = value;
}
public TreeNode<T> this[int i]
{
get { return _children[i]; }
}
public TreeNode<T> Parent { get; private set; }
public T Value { get { return _value; } }
public ReadOnlyCollection<TreeNode<T>> Children
{
get { return _children.AsReadOnly(); }
}
public TreeNode<T> AddChild(T value)
{
var node = new TreeNode<T>(value) {Parent = this};
_children.Add(node);
return node;
}
public TreeNode<T>[] AddChildren(params T[] values)
{
return values.Select(AddChild).ToArray();
}
public bool RemoveChild(TreeNode<T> node)
{
return _children.Remove(node);
}
public void Traverse(Action<T> action)
{
action(Value);
foreach (var child in _children)
child.Traverse(action);
}
public IEnumerable<T> Flatten()
{
return new[] {Value}.Union(_children.SelectMany(x => x.Flatten()));
}
}
Note: I could easily do a recursive BFS in C#, But found this one tougher
Image of sample tree structure
Do a recursive traversal of the tree. You collect the result of evaluating each child node, then apply your logical operation and return the result. The basic logic would be like below.
The code is a C#-like pseudocode. It's not clear to me from the code you posted how you differentiate between operator nodes (AND and OR) from nodes that have values True and False. But you should be able to use this basic algorithm with a few changes to fit your code.
bool EvaluateNode(TreeNode node)
{
// if it's a child node, return its value
if (node has no children)
{
return node._value;
}
switch node.Operator
{
case operator.AND:
// for AND, we can shortcut the evaluation if any child
// returns false.
for each child
{
if (EvaluateNode(child) == false)
return false;
}
// all children returned true, so it's true
return true;
case operator.OR:
// for OR, we can shortcut the evaluation if any child
// returns true.
for each child
{
if (EvaluateNode(child) == true)
return true;
}
// none were true, so must be false
return false;
default:
// Unknown operator. Some error.
break;
}
}
If you don't want to do shortcut evaluation, this still works. You just change your loops slightly. For example, the AND case would be:
bool result = true;
for each child
{
result = result & EvaluateNode(child);
}
return result;
And the OR case would be:
bool result = false;
for each child
{
result = result | EvaluateNode(child);
}
return result;

how to find a NodeData in tree of Nodes?

I have a Node structure as below,this Node has stringdata and list of nodes as it's children. I wanted to search a data in this tree
I wrote a recursive function FindNode(Node intree,string target)
public class Node
{
public string Data;
public List<Node> Children = new List<Node>();
//some code
public Node(string r)
{
this.Data = r;
}
public string getData()
{
return this.Data;
}
//some code
public List<Node> getchildren()
{
return this.Children;
}
//some code
}
target is the string which I want to find and the intree is the begining of the tree(ROOT)
I have problem after while loop what should I return after that?
If I am wrong how should I write it?
public Node FindNode(Node intree,string target)
{
if(intree.getData()==target)
return intree;
else
{
while(intree.getchildren()!=null)
{
foreach(Node n in intree.getchildren())
{
FindNode(n,target);
}
}
}
}
Use this one:
public Node FindNode(Node intree,string target)
{
if(intree.getData()==target)
return intree;
else
{
foreach(Node n in intree.getchildren())
{
Node node = FindNode(n,target) ; //CHECK FOR RETURN
if(node != null)
return node;
}
}
return null;
}
The difference is that I checked for return of FindNode method, and if it's not null, return result.
Just note that in case of dupplicated nodes in the tree (nodes with the same string) it will return first occuarance.
Given that there could be more than one match in the tree you would be better off returning an IEnumerable<Node>. Also you don't need to put those odd get methods in there. And finally did you mean to only search leaf nodes or did you want to search all nodes (the else statement)?
public IEnumerable<Node> FindNode(Node intree,string target)
{
if(intree.Data ==target)
yield return intree;
foreach (var node in intree.Children.SelectMany(c => FindNode(c, target))
yield return node;
}
If you want the first matching node, just call First() on the result. If you want to make sure there is only one, call Single() on it.
I would recommend you to return null and apply check where you are calling this method that if null is returned then it means no node found. Code is as follow
public static Node FindNode(Node intree, string target)
{
if (intree.getData() == target)
return intree;
foreach (Node node in intree.getchildren())
{
Node toReturn = FindNode(node, target);
if (toReturn != null) return toReturn;
}
return null;
}
public Node FindNodeRecursively(Node parentNode, string keyword)
{
if(parentNode.getData() == keyword)
{
return parentNode;
}
else
{
if(parentNode.Children != null)
{
foreach(var node in parentNode.Children)
{
var temp = FindNodeRecursively(node, keyword);
if(temp != null)
return temp;
}
}
return null;
}
}

Categories