I'm developing an ASP.NET 4.0 web application and I am using a TreeView control. I have one problem that I really can't understand why this is happening. I have checkboxes associated with the tree items.
If the checkbox is not checked everything works just fine, but when I execute the following line:
node.ChildNodes.Clear();
If the checkbox is checked for the node, the node.Parent is null after the Clear(). If it is not checked, parent is still correct. I really can't understand why the clearing of the childnodes collection will also clear my parent reference. I actually don't use or modify the checked property within this call. I am also 100% sure that my parent isn't a child to my node as well (why would it differ if it checked or not).
The workaround I need to use in order for the code to work as expected is:
TreeNode[] checkedNodes = new TreeNode[tvResults.CheckedNodes.Count];
tvResults.CheckedNodes.CopyTo(checkedNodes, 0);
foreach (TreeNode checkedNode in checkedNodes) // Uncheck all nodes temporary.
checkedNode.Checked = false;
node.ChildNodes.Clear(); // Now it is ok to clear and parent is "saved".
foreach (TreeNode checkedNode in checkedNodes) // Recheck all checked nodes again.
checkedNode.Checked = true;
Any idea anyone about this issue?
Thanks,
Mattias
PS! Please be kind, this is my first question ever...
Below is the code from ASP.NET TreeNodeCollection.Clear (from .NET 4.5). As you can see, it does clear all checked nodes without performing any validation. So this is by design (rather a bug by design) and not a bug in your code. My advice would be add an extension method that performs the workaround you listed in the question so that you can easily reuse it.
// System.Web.UI.WebControls.TreeNodeCollection
/// <summary>Empties the <see cref="T:System.Web.UI.WebControls.TreeNodeCollection" /> object.</summary>
public void Clear()
{
if (this.Count == 0)
{
return;
}
if (this._owner != null)
{
TreeView owner = this._owner.Owner;
if (owner != null)
{
if (owner.CheckedNodes.Count != 0)
{
owner.CheckedNodes.Clear();
}
for (TreeNode treeNode = owner.SelectedNode; treeNode != null; treeNode = treeNode.Parent)
{
if (this.Contains(treeNode))
{
owner.SetSelectedNode(null);
break;
}
}
}
}
foreach (TreeNode current in this._list)
{
current.SetParent(null);
}
this._list.Clear();
this._version++;
if (this._isTrackingViewState)
{
this.Log.Clear();
}
this.Log.Add(new TreeNodeCollection.LogItem(TreeNodeCollection.LogItemType.Clear, 0, this._isTrackingViewState));
}
Related
In my Program there's is a user right, I'm taking those rights from the user rights that I have saved in the SQL database to the static variables when user login to the system, I want to restrict user from clicking not allowed TreeNodes. So It's checking from the static variable values. In my Form Load, I wrote:
if (bl_Static.AddReq != true)
{
treeView1.Nodes.RemoveAt(6);
}
But It's not working. Can you help me with this, please?
I think you are calling the RemoveAt method of the wrong parent node so the target node
won't be removed if it is not in the TreeNodeCollection of treeView1.Nodes.
To solve the problem, find the target node by it's unique key/name using the TreeNodeCollection.Find method and check whether it is a root or child node to call the Remove method of the right collection:
if (!bl_Static.AddReq)
{
var tarNode = treeView1.Nodes.Find("GetTheNameFromTheDesigner", true).FirstOrDefault();
if(tarNode != null)
{
if (tarNode.Parent != null)
tarNode.Parent.Nodes.Remove(tarNode);
else
treeView1.Nodes.Remove(tarNode);
}
}
I have a tree with multiple nodes with different depth.
So I need to use the check boxes for deleting nodes not the selection method.
I have tried this code and it worked good,
if anyone have a comment please come up with it.
ArrayList checkedNodes = new ArrayList();
if (elementsHierTree.CheckedNodes.Count != 0)
{
foreach (TreeNode nodee in elementsHierTree.CheckedNodes)
{
if (nodee.Parent != null)
{
checkedNodes.Add(nodee);
}
}
}
foreach (TreeNode chNode in checkedNodes)
{
chNode.Parent.ChildNodes.Remove(chNode);
}
I've created a directory and file browser TreeView on the left side. I want the users to be able to browse the tree and check the files and directories that they would like to move to another treeview.
The other TreeView is a user control I found online called TreeViewColumn. I will be using that control to allow the user to add other data (categories, attributes) to the files and folders selected.
The trouble I'm running into is two-fold, I need to recursively add all children (I can figure this out) but I need to add unchecked parents to checked children (to preserve the hierarchy).
private void IterateTreeNodes(TreeNode originalNode, TreeNode rootNode)
{
//Take the node passed through and loop through all children
foreach (TreeNode childNode in originalNode.Nodes)
{
// Create a new instance of the node, will need to add it to the recursion as a root item
// AND if checked it needs to get added to the new TreeView.
TreeNode newNode = new TreeNode(childNode.Text);
newNode.Tag = childNode.Tag;
newNode.Name = childNode.Name;
newNode.Checked = childNode.Checked;
if (childNode.Checked)
{
// Now we know this is checked, but what if the parent of this item was NOT checked.
//We need to head back up the tree to find the first parent that exists in the tree and add the hierarchy.
if (tvSelectedItems.TreeView.Nodes.ContainsKey(rootNode.Name)) // Means the parent exist?
{
tvSelectedItems.TreeView.SelectedNode = rootNode;
tvSelectedItems.TreeView.SelectedNode.Nodes.Add(newNode);
}
else
{
AddParents(childNode);
// Find the parent(s) and add them to the tree with their CheckState matching the original node's state
// When all parents have been added, add the current item.
}
}
IterateTreeNodes(childNode, newNode);
}
}
private TreeNode AddParents(TreeNode node)
{
if (node.Parent != null)
{
//tvDirectory.Nodes.Find(node.Name, false);
}
return null;
}
Could anyone help with this code so that it recursively adds checked nodes (and their parent, regardless of checked state). I need to maintain directory hierarchy.
Thanks for any help!
A rather (not-so-clean and not-preferred) solution could be to clone the tree first, and then remove unchecked branches.
Else, when you are adding a node, write a recursive method to traverse through node's parent node until you hit the root. And simply optimize it by checking if childNode.parent already exists, just ignore the branch and move on. i.e. Backtrack to root node.
I got it working. I was already aware of what #Yahya was saying, I was hoping for an easier way / better approach.
The code below is certainly not optimal, I will continue improving it on my end but at this point it is looking through a treeview on the left and copying all of the checked items (and their parents - regardless of CheckedState) to a treeview on the right.
Hopefully this helps someone and thanks for answering #Yahya.
I'm open to improvements but keep in mind this is a one-time use utility.
private void cmdMoveRight_Click(object sender, EventArgs e)
{
tvSelectedItems.TreeView.Nodes.Clear();
// Traverse first level Tree Nodes
foreach (TreeNode originalNode in tvDirectory.Nodes)
{
TreeNode newNode = new TreeNode(originalNode.Text);
newNode.Name = originalNode.Name;
newNode.Tag = originalNode.Tag;
newNode.Checked = originalNode.Checked;
//Only add to the new treeview if the node is checked
if (originalNode.Checked)
{
tvSelectedItems.TreeView.Nodes.Find(originalNode.Parent.Name,true)[0].Nodes.Add(newNode);
}
//Start recursion - this will be called for each first level node - there should technically only be 1 "ROOT" node.
IterateTreeNodes(originalNode, newNode);
}
}
private void IterateTreeNodes(TreeNode originalNode, TreeNode rootNode)
{
//Take the node passed through and loop through all children
foreach (TreeNode childNode in originalNode.Nodes)
{
// Create a new instance of the node, will need to add it to the recursion as a root item
// AND if checked it needs to get added to the new TreeView.
TreeNode newNode = new TreeNode(childNode.Text);
newNode.Tag = childNode.Tag;
newNode.Name = childNode.Name;
newNode.Checked = childNode.Checked;
if (childNode.Checked)
{
// Now we know this is checked, but what if the parent of this item was NOT checked.
//We need to head back up the tree to find the first parent that exists in the tree and add the hierarchy.
TreeNode[] nodestest = tvSelectedItems.TreeView.Nodes.Find(childNode.Parent.Name, true);
if (nodestest.Length > 0)
{
tvSelectedItems.TreeView.Nodes.Find(childNode.Parent.Name,true)[0].Nodes.Add(newNode);
}
else
{
AddParents(childNode);// Find the parent(s) and add them to the tree with their CheckState matching the original node's state
}
}
//recurse
IterateTreeNodes(childNode, newNode);
}
}
private void AddParents(TreeNode node)
{
if (node.Parent != null)// Check if parent is null (would mean we're looking at the root item
{
TreeNode[] nodestest = tvSelectedItems.TreeView.Nodes.Find(node.Parent.Name, true);
if (nodestest.Length > 0)
{
TreeNode[] nodes = tvDirectory.Nodes.Find(node.Name, true);
TreeNode newNode = new TreeNode(nodes[0].Text);
newNode.Name = nodes[0].Name;
newNode.Tag = nodes[0].Tag;
newNode.Checked = nodes[0].Checked;
tvSelectedItems.TreeView.Nodes[node.Parent.Name].Nodes.Add(newNode);
}
else
{
AddParents(node.Parent);
TreeNode newNode = new TreeNode(node.Text);
newNode.Name = node.Name;
newNode.Tag = node.Tag;
newNode.Checked = node.Checked;
tvSelectedItems.TreeView.Nodes.Find(node.Parent.Name,true)[0].Nodes.Add(newNode);
}
}
else // deal with root node
{
TreeNode rootNode = new TreeNode(node.Text);
rootNode.Name = node.Name;
rootNode.Tag = node.Tag;
rootNode.Checked = node.Checked;
tvSelectedItems.TreeView.Nodes.Add(rootNode);
}
}
I have been working on this for a while, but cannot resolve the issue. I have searched S/O & Google, but no luck. Hoping someone on here can help resolve this.
I am not able to display the child nodes in my TreeView control. The data is being retrieved from a database.
The root node appears fine, but there are not child nodes displayed. How can I get the child nodes to be displayed?
My code is:
private void PopulateTreeNode(DataSet dsList)
{
var treeNode = new TreeNode();
foreach (DataRow dr in dsList.Tables[0].Rows)
{
if (dr["RecordTypeID"].ToString() == "1")
{
TreeNode NewNode = new TreeNode(dr["CustomerName"].ToString(), dr["customerID"].ToString());
treeCustomer.Nodes.Add(NewNode);
}
else if (dr["RecordTypeID"].ToString() == "2")
{
TreeNode pNode = new TreeNode(dr["CustomerName"].ToString(), dr["customerID"].ToString());
pNode.ChildNodes.Add(pNode);
}
else if (dr["RecordTypeID"].ToString() == "3")
{
TreeNode pNode = new TreeNode(dr["CustomerName"].ToString(), dr["customerID"].ToString());
pNode.ChildNodes.Add(pNode);
}
}
treeCustomer.Nodes.Add(treeNode);
treeCustomer.DataBind();
}
You don't need to call treeCustomer.DataBind() if you are manually adding nodes like this. It is probably clearing out your tree.
Have you tried calling treeCustomer.ExpandAll() ?
You may also need to set various properties of the treeview too; regarding displaying expand images etc..
It looks like you're adding pNode to the child nodes of pNode. This means it is never getting added to treeCustomer since only treeNode is being added to treeCustomer. It should probably be added to the child nodes of treeNode, or possibly added as a node of treeNode.
I am creating an application with C# WPF:
I have have dynamically generated treeview
In that treeview I have a TreeViewItem called BoekenLijst.
There I generate dynamic TreeViewItems like "the hobbit". The book content, like "the hobbit", I store in the Content property of a Checkbox.
So the treeview will look like this:
Treeview>
TreeViewItem(BoekenLijst)>
The Hobbit
Code Complete
I want to put the checked TreeViewItems in a ListBox so I did the following:
private List<TreeViewItem> GetAllItemContainers(TreeViewItem itemsControl)
{
List<TreeViewItem> allItems = new List<TreeViewItem>();
for (int i = 0; i < itemsControl.Items.Count; i++)
{
// try to get the item Container
TreeViewItem childItemContainer = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
// the item container maybe null if it is still not generated from the runtime
if (childItemContainer != null)
{
allItems.Add(childItemContainer);
List<TreeViewItem> childItems = GetAllItemContainers(childItemContainer);
foreach (TreeViewItem childItem in childItems)
{
CheckBox checkBoxTemp = childItem.Header as CheckBox;
if (checkBoxTemp != null)
optieListBox.Items.Add(checkBoxTemp.Content);
allItems.Add(childItem);
}
}
}
return allItems;
}
The problem is, it won't go into: foreach (TreeViewItem childItem in childItems)
Can someone help me out?
Have you tried running it through the Visual Studio debugger? If you insert the break point where the error is getting thrown, then you should be able to get a stack trace of what's going on, and if it's anything like the Eclipse debugger (I've not used VS in a while) you should be able to click on any variable in the code or hold the mouse over it, and it will display the current value of that variable in memory.
But I echo what the others say, try and figure out for yourself, take your time, and work through it step by step. I had to learn that myself, and I still get it wrong as I always forget to use the debugger...ask my team leader if you don't believe me :-)
Welshboy