I need to construct a huge treeview from a composite database table with Grouping
.
Grouping
is, what we see in SQL Server Management Studio Express. After a Database
node, some fixed folders are shown (like, Database Diagrams
, Tables
, Views
, Synonyms
, Programmability
and Security
) and children are grouped in those folders.
Up to this point I have used AfterSelect
event and handler to achieve this.
But the problem with AfterSelect
is, before selecting the node, the viewer is not able to know whether there is any child available. This is because, the expandable plus
sign is not visible.
I want to use BeforeExpand
. But the problem with BeforeExpand
is, it works if the children are already populated. In that case, when I click groups, nothing happens.
How to solve this?
So codes/web-link will be appreciated.
What I usually do is to add a "dummy child node" wherever there may be children that should be loaded in a lazy manner. This will make the parent have the plus sign, and then you can add code to the AfterExpand event where you do the following:
I typically give the dummy node a text like "Loading data. Please wait..." or so, so that the user gets some info on what is going on.
Update
I put together a simple example:
public class TreeViewSample : Form
{
private TreeView _treeView;
public TreeViewSample()
{
this._treeView = new System.Windows.Forms.TreeView();
this._treeView.Location = new System.Drawing.Point(12, 12);
this._treeView.Size = new System.Drawing.Size(200, 400);
this._treeView.AfterExpand +=
new TreeViewEventHandler(TreeView_AfterExpand);
this.ClientSize = new System.Drawing.Size(224, 424);
this.Controls.Add(this._treeView);
this.Text = "TreeView Lazy Load Sample";
InitializeTreeView();
}
void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
{
if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Tag == "dummy")
{
// this node has not yet been populated, launch a thread
// to get the data
ThreadPool.QueueUserWorkItem(state =>
{
IEnumerable<SomeClass> childItems = GetData();
// load the data into the tree view (on the UI thread)
_treeView.BeginInvoke((Action)delegate
{
PopulateChildren(e.Node, childItems);
});
});
}
}
private void PopulateChildren(TreeNode parent, IEnumerable<SomeClass> childItems)
{
TreeNode child;
TreeNode dummy;
TreeNode originalDummyItem = parent.Nodes[0];
foreach (var item in childItems)
{
child = new TreeNode(item.Text);
dummy = new TreeNode("Loading. Please wait...");
dummy.Tag = "dummy";
child.Nodes.Add(dummy);
parent.Nodes.Add(child);
}
originalDummyItem.Remove();
}
private IEnumerable<SomeClass> GetData()
{
// simulate that this takes some time
Thread.Sleep(500);
return new List<SomeClass>
{
new SomeClass{Text = "One"},
new SomeClass{Text = "Two"},
new SomeClass{Text = "Three"}
};
}
private void InitializeTreeView()
{
TreeNode rootNode = new TreeNode("Root");
TreeNode dummyNode = new TreeNode("Loading. Please wait...");
dummyNode.Tag = "dummy";
rootNode.Nodes.Add(dummyNode);
_treeView.Nodes.Add(rootNode);
}
}
public class SomeClass
{
public string Text { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With