Does the event handler get called for each visible node to determine if the expand hint (+) should be showed?
If yes, this is not a usable concept for me. I would like to give that indication without actually loading the children.
When I load my root nodes, I already know if they have children (by grouping and count() in the database).
The Idea now is to show the user how many children there are and let him decide if he wants to expand (and wait for the nodes to be loaded).
Regards Erwin
12 Answers, 1 is accepted
The new NodesNeeded event is fired only when a node is in expanded state and its Nodes collection is empty. You can expand a node that is currently not into view programmatically and the visibility state of the node will not be taken into consideration by the event handler. This gives us good performance, decreased possible recursion issues and simplified API which only has the NodesNeeded event.
All the best,Julian Benkov
the Telerik team
The NodesNeeded event is fired initially when RadTreeView is loaded. If the Parent property is null, this means that the event is fired for the root level, so we pass the desired root node(s) to the Nodes collection that comes from the event arguments. Further, the NodesNeeded is fired once again for each of the created root nodes even before we try to expand them. As a result, we load the children of the root nodes before we expand these root nodes and this is how the nodes know whether to show the expander or not. When we expand a root node, the NodesNeeded event is fired for each of the child nodes where we pass the children of the child nodes. So, the child nodes know whether to show the expander image or not as well.
We will consider extending the Load-On-Demand feature, showing the expander element for each node.
Best wishes,
Julian Benkov
the Telerik team
that's exactly what I suspected. Unfortunately that makes the feature unusable for many scenarios. If you really care about performance, you can model the query so that when loading the root nodes, you already know if there are child nodes. That makes 1 roundtrip to the database instead of 30 or whatever visible root nodes you have.
In my scenario, the demand loading with NodesNeeded is most of the times much slower than loading the tree in one go with no on demand loading at all, since that also requires just 1 roundtrip to the database. The thing is, that the round trip to a database including query parsing etc. is extremely expensive.
Not that much of an issue though, when you still provide a way to manually load nodes on expand events. But see my other post about display glitches with that approach..
regards
Erwin
I made also another solution of Load-On-Demand functionality using NodeExpandedChanged, CreateNode and NodeFormatting events:
public partial class Form6 : Form{ class LazyTreeNode : RadTreeNode { private bool loaded; public bool Loaded { get { return loaded; } set { loaded = value; } } } public Form6() { InitializeComponent(); radTreeView1.ShowLines = true; using (radTreeView1.DeferRefresh()) { for (int i = 0; i < 10; i++) { radTreeView1.Nodes.Add("RootNode" + i.ToString()); } } } private void radTreeView1_NodeExpandedChanged(object sender, Telerik.WinControls.UI.RadTreeViewEventArgs e) { LazyTreeNode node = e.Node as LazyTreeNode; if (node.Loaded) { return; } node.Nodes.BeginUpdate(); for (int i = 0; i < 10; i++) { node.Nodes.Add("ChildNode" + i.ToString()); } node.Nodes.EndUpdate(); node.Loaded = true; } private void radTreeView1_CreateNode(object sender, Telerik.WinControls.UI.CreateTreeNodeEventArgs e) { e.Node = new LazyTreeNode(); } private void radTreeView1_NodeFormatting(object sender, TreeNodeFormattingEventArgs e) { e.NodeElement.ExpanderElement.Visibility = Telerik.WinControls.ElementVisibility.Visible; }}This solution has a known issue concerning the indent of the RadTreeNodes at the different levels. In Q1 2011 SP1 the desired behavior will be natively supported by RadTreeView, the layout issue will be addressed and the NodeNeeded event will be raised only the currently visible and expanded level.
Best wishes,
Julian Benkov
the Telerik team
Regards
Erwin
Is there an ETA for SP1? Will a work-around similar to the one presented be required or will there be a property to set when the NewNodesNeeded event gets fired (on node displayed versus on node expanded)?
You can download and use new Q1 2011 SP1 release. In the new improved implementation of load-on-demand functionality the NodesNeeded event is raised only for expanded parent node. This is the new default behavior of RadTreeView control, for other cases when you want to know the nodes for inner level in advance, then must set the new LazyMode property of treeview to false. We also added support to make RadTreeView work properly with the approach valid for the old version of RadTreeView control using Loaded property in this example:
public partial class Form4 : Form{ public Form4() { InitializeComponent(); this.radTreeView1.NodesNeeded += new NodesNeededEventHandler(radTreeView1_NodesNeeded); using (radTreeView1.DeferRefresh()) { for (int i = 0; i < 10; i++) { radTreeView1.Nodes.Add("RootNode" + i.ToString()); } } } void radTreeView1_NodesNeeded(object sender, NodesNeededEventArgs e) { } private void radTreeView1_NodeExpandedChanged(object sender, Telerik.WinControls.UI.RadTreeViewEventArgs e) { LazyTreeNode node = e.Node as LazyTreeNode; if (node.Loaded) { return; } node.Nodes.BeginUpdate(); for (int i = 0; i < 10; i++) { node.Nodes.Add("ChildNode" + i.ToString()); } node.Nodes.EndUpdate(); node.Loaded = true; } private void radTreeView1_CreateNode(object sender, Telerik.WinControls.UI.CreateTreeNodeEventArgs e) { e.Node = new LazyTreeNode(); } class LazyTreeNode : RadTreeNode { private bool loaded; public bool Loaded { get { return loaded; } set { loaded = value; } } }}I hope this helps.
All the best,Julian Benkov
the Telerik team
I checked with the most trivial tree in my app and seems to work quite well.
In other trees I'll have to work a bit on the load logic.
I guess the release notes for SP1 should mention this as a breaking change compared to 2011Q1.
Regards
Erwin
When I use the new NodesNeedes event, I get 2 events when I start filling the root tree.
Both e arguments have the e.parent set to null.
Another question: When I use this event, I cannot dermine which node is calling the event.
What I want is load the root three when the app starts, each created root node will call the nodesneeded event, so I can determine if I need to fill his nodes collection with nodes.
But right now, when the nodesneeded event runs, I cannot deterine this.
Can you please help?
Regards,
Jeroen
I do exaclty what you want to do with loading the root nodes when the control loads and loading child nodes on demand.
If the parent is null, I just ignore the NodesNeeded handler.
If the parent node is not null, I use it's Tag Property, where I previously stored the key to load child nodes.
hope this helps.
Erwin
Like Erwin suggested, you can load root nodes outside the event handler and use the event for the internal Nodes collection:
public partial class Form16 : Form{ public Form16() { InitializeComponent(); //root Nodes for (int i = 0; i < 50; i++) { RadTreeNode childNode = new RadTreeNode(string.Format("Node{0}", i)); this.radTreeView1.Nodes.Add(childNode); } } private void radTreeView1_NodesNeeded(object sender, Telerik.WinControls.UI.NodesNeededEventArgs e) { if (e.Parent == null) { return; } for (int i = 0; i < 50; i++) { RadTreeNode childNode = new RadTreeNode(string.Format("Node{0}", i)); e.Nodes.Add(childNode); } }}
Kind regards,
Julian Benkov
the Telerik team