I am trying to dynamically populate a treeview object on a sharepoint webpart. For some reason, the node population is triggered automatically and without user input. Below is a sample of how I set up the tree and webpart.
Any suggestions on how to prevent the automatic populate would be appreciated.
The following is in the createchildcontrols method:
this.Tree = new TreeView();
this.Tree.EnableClientScript = false;
this.Tree.PopulateNodesFromClient = true;
this.Tree.Nodes.Add(this.FetchTreeNode());
this.Tree.TreeNodePopulate += new TreeNodeEventHandler(Tree_TreeNodePopulate);
The handler looks like this:
void Tree_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
List<MyNode> children = this.FetchChildren(e.Node.Value);
foreach (MyNode child in children)
{
TreeNode node = new TreeNode(child.Name, child.UniqueId, child.IconPath);
node.PopulateOnDemand = true;
node.SelectAction = TreeNodeSelectAction.Expand;
e.Node.ChildNodes.Add(node);
}
}
I've been banging my head on this one for a long time, any suggestions would be appreciated.
So I finally figured this out... for some reason, the default behavior of the treeview was to be expanded, so it would call the treenode populate function right off the bat. I was able to get this to work by calling the treeview.collapseall() method.
Related
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..
Is there a way of populating a treeview including the parent's sub folder? My code only can only view files on its parent folder but once it in a sub folder it won't open.
Main problem: I can't open a file when it's inside a sub folder of my MapPath
Here's mine, so far it only gets the parent node it doesn't get the parent's sub folder:
protected void Page_Load(object sender, EventArgs e)
{
TreeView1.Nodes[0].Value = Server.MapPath("~/Files");
}
protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
if (e.Node.ChildNodes.Count == 0)
{
DirectoryInfo directory = null;
directory = new DirectoryInfo(e.Node.Value);
foreach (DirectoryInfo subtree in directory.GetDirectories())
{
TreeNode subNode = new TreeNode(subtree.Name);
subNode.Value = subtree.FullName;
try
{
if (subtree.GetDirectories().Length == 0 | subtree.GetFiles().Length == 0)
{
subNode.SelectAction = TreeNodeSelectAction.SelectExpand;
subNode.PopulateOnDemand = true;
subNode.NavigateUrl = "";
}
}
catch
{
}
e.Node.ChildNodes.Add(subNode);
}
foreach (FileInfo fi in directory.GetFiles())
{
TreeNode subNode = new TreeNode(fi.Name);
e.Node.ChildNodes.Add(subNode);
subNode.NavigateUrl = "Files/" + fi.Name;
}
}
}
There's absolutely nothing wrong with your code. I've run a test it works like a charm. So, a few things to point out which are NOT exactly clear in your question.
1.
You need to hook the TreeView1_TreeNodePopulate to your TreeView control. You can do that declaratively from the markup...
<asp:TreeView ID="TreeView1" runat="server" OnTreeNodePopulate="TreeView1_TreeNodePopulate">
or, imperatively from code behind...
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
TreeView1.TreeNodePopulate += TreeView1_TreeNodePopulate;
}
otherwise this event handler will never get hit
2.
In addition to hooking up the OnTreeNodePopulate event you need to add at least one node from the markup and set its PopulateOnDemand property to true...
<Nodes>
<asp:TreeNode PopulateOnDemand="true" Text="Root"></asp:TreeNode>
</Nodes>
if you don't set this property this event will never get triggered. Another reason to add this "root" node is to avoid an IndexOutOfRangeException or NullReference exception here...
TreeView1.Nodes[0].Value = Server.MapPath("~/Files");
Keeping all that in mind, it should work just fine
Edit based on comment
I didn't noticed the bit where you said you want to open the files when the tree node is clicked. And that happens because you are passing the url when creating and adding the nodes. Basically I'd recommend not using Server.MapPath on page load, add the virtual server path only...
TreeView1.Nodes[0].Value = "~/Files";
then use Server.MapPath when creating the DirectoryInfo object...
directory = new DirectoryInfo(Server.MapPath(e.Node.Value));
and set the value of the tree node (inside the "directories" iteration) by appending a parent value's...
subNode.Value = string.Format("{0}/{1}", e.Node.Value, subtree.Name);
and finally, within the "files" iteration, set the NavigateUrl's property of the node like below...
subNode.NavigateUrl = string.Format("{0}/{1}", e.Node.Value, fi.Name);
That should give you a proper link in your file nodes. Notice, that this is similar to issuing an http request using a web browser and the request will be handled by IIS and the ASP.NET pipeline...which means that you will only be able to see files that can be handled by IIS by default (e.g. images, etc)
I have a TreeView that is displayed inside a panel. The data in the TreeView is based on data returned from the database. The first time, the data is correct. The second time, the TreeView is not refreshed, and the previous data is still showing in the tree. I checked the list that contain the data. The list returned the correct data. I've Google the issue, and could not resolved it with some of the answers that were posted. Here is a sample code of how the TreeView is being created and added to the Panel.
ReportGroups gr = new ReportGroups();
var Name = gr.GetReportName(groupID);
TreeView tr = new TreeView();
tr.BeginUpdate();
tr.Size = new Size(570, 600);
tr.Name = "Home";
tr.Nodes.Add("Reports Name");
tr.CheckBoxes = true;
if (Name.Count() > 0)
{
foreach (var item in Name)
{
if (item != null)
{
tr.Nodes[0].Nodes.Add(item.reportName);
}
}
}
tr.Nodes[0].ExpandAll();
tr.EndUpdate();
this.pDisplayReportName.Width = tr.Width * 2;
this.pDisplayReportName.Height = 300;
this.pDisplayReportName.Controls.Add(tr);
this.pDisplayReportName.Refresh();
What am I doing wrong?
try to add this.pDisplayReportName.Clear(); so data will not double up. :)
The easy option would be to use this.pDisplayReportName.Controls.Clear(); just after tr.EndUpdate();. But, this would cause an issue if you have other controls within the same Panel.
The best option would be to use this.pDisplayReportName.Controls.RemoveByKey("MyTree"); instead of this.pDisplayReportName.Controls.Clear();
And, another option would be to add a TreeView in design time (with name tr) rather than dynamically to the panel. Then, use tr.Nodes.Clear(); before tr.BeginUpdate(); and remove following two lines from your code.
TreeView tr = new TreeView();
.
.
.
this.pDisplayReportName.Controls.Add(tr);
Cheers
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 have a TreeView in my Windows Form user interface.
I want to fill it up from a database, but it does not refresh ever, even though if I WriteLine() every node, it is in memory as I expect.
In order to make it more easy to understand, I wrote a little example program that only has one button that creates a TreeView and a TreeView called treeView1 to display its content.
If anyone can tell me where I have misunderstood the use of the TreeView, it would be a tremendous help.
private void button1_Click(object sender, EventArgs e)
{
// create a tree
TreeView t = new TreeView();
TreeNode[] child = new TreeNode [1];
child[0]=new TreeNode("myCat");
child[0].Name = "IndependantOne";
TreeNode categoryNode = new TreeNode("catIdTag", child);
categoryNode.Name = "Citizen Cat 5239002147";
t.Nodes.Add(categoryNode);
// some stuff under the first node
TreeNode[] mouseNode = new TreeNode[1];
mouseNode[0] = new TreeNode("myMouse");
mouseNode[0].Name = "SqueakyOne";
TreeNode[] childItem = new TreeNode[1];
childItem[0] = new TreeNode("mouseIdTag", mouseNode);
childItem[0].Name = "Citizen Mouse 54655654649";
TreeNode eltNode = new TreeNode("Cheese", childItem);
eltNode.Name = "Emmental";
t.Nodes["Citizen Cat 5239002147"].Nodes.Add(eltNode);
// fill in the winform treeview
if (t != null)
{
//treeView1.Visible = false;
treeView1.BeginUpdate();
treeView1.Nodes.Clear();
treeView1.TopNode = t.TopNode;
foreach (TreeNode n in t.Nodes)
{
treeView1.Nodes.Add(n);
System.Diagnostics.Debug.WriteLine("Category Node contains: " + treeView1.Nodes[n.Name].Name + " at " + treeView1.Nodes[n.Name].Level);
foreach (TreeNode no in treeView1.Nodes[n.Name].Nodes)
{
System.Diagnostics.Debug.WriteLine("Category Node Nodes contains: " + no.Name);
}
}
/*
This part I tried and it doesn't work either, still add it in the question if anyone knows if it's wiser?
this.treeView1 = t;
this.treeView1.Location = new System.Drawing.Point(233, 12);
this.treeView1.Name = "treeView1";
this.treeView1.Size = new System.Drawing.Size(351, 277);
this.treeView1.TabIndex = 11;
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
*/
treeView1.EndUpdate();
this.treeView1.Update();
this.treeView1.Refresh();
treeView1.Show();
//this.Refresh();
}
}
I also tried setting the treeView1 with
treeView1 = t;
It was not a success...
change
treeView1.Nodes.Add(n);
with
treeView1.Nodes.Add((TreeNode)n.Clone());
You cannot host the same node in more than one TreeView control.
Alternatively, you can remove nodes from source TreeView before adding them to other TreeView:
while(t.Nodes.Count != 0)
{
var node = t.Nodes[0];
t.Nodes.RemoveAt(0);
treeView1.Nodes.Add(node);
}
And I hope that there is a real reason why you create and fill tree view in your method instead of directly filling an already existing one. If it is not an intended behavior, remove the if block completely and change TreeView t = new TreeView(); to var t = treeView1.
This behavior is expected because with this code you`re confusing node-to-treeview relationship nature of the native .NET treeview control. Instead when moving nodes between treeviews (t -> treeView1) you need to clone them as suggested. Without that moved node still linked with the old treeview (see node.Treeview property) and because original tree (t) is not visible/added to any parent (form), I guess node will be invisible as well.
Also, the way you`re working with data loading (through creating new treeview) is pretty bad pattern. Instead you need to download your data (async I guess) into a temp buffer and recreate the treeView1 at once when data will be available with BeginUpdate/EndUpdate calls.
PS. Replacing treeView1 variable with 't' won't work as well because you don't replace the treeview control instance in the parent form/panel Controls property with this code.