I need to populate a treeview in asp.net and I need a recursive function to insert all nodes and child nodes on the treeview.
I have two methods:
GetRootPage()
GetPagesByParent(Page parent) -> returns a IEnumerable<Page> with the page childs.
Anyone can help me with the recursive logic to build the tree?
I sincerely hope this isn't a homework question. That being said, something like this should get you started:
Disclaimer:
I have not tested or verified this, and it is intended only to serve as a rough example
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var pages = GetPagesByParent(Page);
if (pages.Count() > 0)
{
var roots = pages.Where(p => p.Parent == null);
foreach (var root in roots)
{
//add the root nodes to the tree
var rootNode = new TreeNode(root.Title);
tree.Nodes.Add(rootNode);
//kick off the recursive population
PopulateChildNodes(pages, root, rootNode);
}
}
}
}
protected void PopulateChildNodes(IEnumerable<Page> pages, Page parent, TreeNode parentNode)
{
var childPages = pages.Where(p => p.Parent == parent);
foreach (var page in pages)
{
var pageNode = new TreeNode(page.Title);
parentNode.Nodes.Add(pageNode);
//populate the children of the pageNode
PopulateChildNodes(pages, page, pageNode);
}
}
Related
I want to get the node's keys just 'only in view' on treeview.
Here is the example;
I am using below code to get all node recursively. It just return all nodes key as expected. however i need to get the keys that only in treeview's view;
public void PrintNodesRecursive(UltraTreeNode oParentNode)
{
if (oParentNode.Nodes.Count == 0)
{
return;
}
foreach (UltraTreeNode oSubNode in oParentNode.Nodes)
{
MessageBox.Show(oSubNode.Key.ToString());
PrintNodesRecursive(oSubNode);
}
}
private void ultraButton3_Click(object sender, EventArgs e)
{
PrintNodesRecursive(ultraTree1.Nodes[0]);
}
I don't know i should follow different path or just reorganize code.
I just stacked after many hours. Need your help.
You can find the first visible node using Nodes collection and IsVisible property of the Node. Then create a recursive method which uses NextVisibleNode to find the next visible node in TreeView.
private void button1_Click(object sender, EventArgs e)
{
var visibleNodes = GetVisibleNodes(treeView1).ToList();
}
public IEnumerable<TreeNode> GetVisibleNodes(TreeView t)
{
var node = t.Nodes.Cast<TreeNode>().Where(x => x.IsVisible).FirstOrDefault();
while (node != null)
{
var temp = node;
node = node.NextVisibleNode;
yield return temp;
}
}
Also as another option, you can rely on Descendants extension method to flatten the TreeView and then using IsVisible property, get all visible nodes.
How can I show the details of a tree node, upon selection, in the same window but separately from the hierarchy tree.
So far I have successfully showed details in the treeview class using this code:
private void buttonCreateTree_Click(object sender, EventArgs e)
{
if (xd != null)
{
TreeNode rootNode = new TreeNode(xd.Root.FirstNode.ToString());
AddNode(xd.Root, rootNode);
treeView1.Nodes.Add(rootNode);
}
if (xd == null)
{
MessageBox.Show("No saved XML file!");
}
}
I've read about tags, but since I'm not very fond of Windows Forms, I don't know how to implement them correctly. What is the correct syntax for the solution?
Update: The details of a tree node are its child components with custom attributes i made like creationDate, LastAccessDate and LastModifiedDate so it needs to show the child elements of a tree node in the same window but apart from the hierarchy tree? that doesn't even make sense O.o
Not sure if that is what you want, or for that matter if you are but you can play with this:
Add a Panel panel1 to the form and hook up this event:
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if (panel1.Controls.Count == 0)
{
panel1.Controls.Add(new TreeView());
panel1.Controls[0].Dock = DockStyle.Fill;
}
TreeView tv = panel1.Controls[0] as TreeView;
if (tv != null)
{
tv.Nodes.Clear();
// option 1 deep copy:
TreeNode tc = (TreeNode)e.Node.Clone();
tv.Nodes.Add(tc);
// option 2 shallow copy, 1 level
TreeNode tn = tv.Nodes.Add(e.Node.Text);
foreach (TreeNode cn in e.Node.Nodes)
tn.Nodes.Add(cn.Text);
}
tv.ExpandAll();
}
Do pick one of the two options and try..
when my page opens it runs this method:
private void PrintRecursive(TreeNode treeNode, string problemValue)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
if (treeNode.Value == problemValue.Split(':')[0])
{
treeNode.Checked = true;
// Then expand the SelectedNode and ALL its parents until no parent found
treeNode.Expand();
while (treeNode.Parent != null)
{
treeNode = treeNode.Parent;
treeNode.Expand();
}
if (problemValue.Contains(":"))
treeNode.Text += problemValue.Split(':')[1];
return;
}
// Print each node recursively.
foreach (TreeNode tn in treeNode.ChildNodes)
{
PrintRecursive(tn, problemValue);
}
}
treeNode.Checked = true works fine!
treeNode.Expand() work great!
however treeNode.Text += problemValue.Split(':')[1]; does nothing!
the value of problemValue is "111:someproblem"
what am i doing wrong?
You need to move
if (problemValue.Contains(":"))
treeNode.Text += problemValue.Split(':')[1];
above the while statement.
The problem is that while you are expanding the parents, you are updating the value of treeNode, so when you try to set the text of treeNode, you are actually at one of the parent nodes.
If you are wanting to see how to do this check out this previous StackOverFlow Posting as well for additional ideas on how to Enumerate TreeNodes Implementing IEnumerable
if you are wanting to print TreeNodes Recursively look at this example
private void PrintRecursive(TreeNode treeNode)
{
// Print the node.
System.Diagnostics.Debug.WriteLine(treeNode.Text);
MessageBox.Show(treeNode.Text);
// Print each node recursively.
foreach (TreeNode tn in treeNode.Nodes)
{
PrintRecursive(tn);
}
}
// Call the procedure using the TreeView.
private void CallRecursive(TreeView treeView)
{
// Print each node recursively.
TreeNodeCollection nodes = treeView.Nodes;
foreach (TreeNode n in nodes)
{
PrintRecursive(n);
}
}
If you want to do this as IEmumerable try the following below
public static class Extensions
{
public static IEnumerable<T> GetRecursively<T>(this IEnumerable collection,
Func<T, IEnumerable> selector)
{
foreach (var item in collection.OfType<T>())
{
yield return item;
IEnumerable<T> children = selector(item).GetRecursively(selector);
foreach (var child in children)
{
yield return child;
}
}
}
}
Here's an example of how to use it
TreeView view = new TreeView();
// ...
IEnumerable<TreeNode> nodes = view.Nodes.
.GetRecursively<TreeNode>(item => item.Nodes);
after tweaking my code for a bit I ended up with this little proof of concept code:
private void button1_Click(object sender, EventArgs e)
{
DepartmentRepository repo = new DepartmentRepository();
var entries = repo.FindAllDepartments(); //Returns IQueryable<Department>
treeView1.BeginUpdate();
var parentDepartments = entries.Where(d => d.IDParentDepartment == null).ToList();
foreach (var parent in parentDepartments)
{
TreeNode node = new TreeNode(parent.Name);
treeView1.Nodes.Add(node);
var children = entries.Where(x => x.IDParentDepartment == parent.ID).ToList();
foreach (var child in children)
{
node.Nodes.Add(child.Name);
}
}
treeView1.EndUpdate();
}
It places every parent Department in the TreeView control and then correctly assigns it's children to the correct Parent.
My problem is, how do I handle children of children? Nested Departments.
I can't seem to wrap my head around it.
Thanks for any guidance.
You need to use recursion:
void LoadNode(TreeNode node, Department d)
{
foreach (var child in d.Children)
{
TreeNode childNode = node.Nodes.Add(child.Name);
LoadNode(childNode, child); // calls the method again for the next level
}
}
Have a look here for sample of recursion:
http://www.codeproject.com/KB/cs/recursionincsharp.aspx
I have a user control in which I need to return child nodes based on parentID. I am able to get the parentID, but don't know the syntax for returning child nodes.
Getting child nodes is pretty straightforward.
Not sure how far you are with your code so here's a complete example with the various options:
using umbraco.presentation.nodeFactory;
namespace cogworks.usercontrols
{
public partial class ExampleUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//If you just want the children of the current node use the following method
var currentNode = Node.GetCurrent();
//If you need a specific node based on ID use this method (where 123 = the desired node id)
var specificNode = new Node(123);
//To get the children as a Nodes collection use this method
var childNodes = specificNode.Children;
//Iterating over nodes collection example
foreach(var node in childNodes)
{
Response.Write(string.Format("{0}<br />", node.Name));
}
//To get the nodes as a datatable so you can use it for DataBinding use this method
var childNodesAsDataTable = node.ChildrenAsTable();
//Databind example
GridViewOnPage.DataSource = childNodesAsDataTable;
GridViewOnPage.DataBind();
}
}
}