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