Currently,I know how to do a lazy implementation of the loading procedure of the nodes in a treeview control, and read the related questions in stackoverflow, but I’m also reading about IHierarchyData and IHierarchicalEnumerable interfaces in asp.net (I didn’t know to code asp.net) that allow to bind a collection to a treeview in order to display the items automatically.
It would like to know if I can do the same in winforms and C#. I think that the interfaces previous mentioned are not available in winforms.
Thanks.
The Windows Forms
TreeViewdoes not know how to bind to anIHierarchyDatainstance, which isn’t surprising given that theIHierarchyDataand related interfaces are intended for consumption by web controls (especially site maps).However, it’s really not too hard to build your own data binding class. This seemed like an interesting problem so I threw one together just for fun. I’ll walk you through the inner workings.
First, create a basic Component class. Visual Studio will start you off with code like this:
One obvious piece of “state” this component needs to have is a mapping from each
TreeNodeto itsIHierarchyData. Now we can hack around this by throwing it in theTreeNode‘sTagproperty, but let’s aim to make this component as non-invasive as possible and keep track of its own state. Hence, we’ll use a dictionary. Add this field to the class:Now, at a minimum, this component needs to know how to populate a specific parent
TreeNodeof aTreeViewclass from its correspondingly boundIHierarchyData, so let’s write that code next:This part should be pretty straightforward. The first method just populates a
TreeNodeCollection(i.e. theNodesproperty of aTreeNode) with the hierarchy obtained from anIHierarchyDatainstance, using theIHierarchyEnumerableinterface. The only really interesting things this method does are:Adding a dummy node when the
IHierarchyDatainstance has children; this makes the “+” visible in the tree view, otherwise we wouldn’t be able to expand any deeper; andAdding the newly-added node to the dictionary with the
IHierarchyDatainstance it matches with.The second method is even simpler, it does the initial “binding work”, replacing whatever is in the root of the tree with our top-level
IHierarchyDatainstance.The next thing our component needs to be able to do is hook the loading events from the
TreeViewto perform lazy-loading. Here’s the code to do that:First two methods should be self-explanatory, and the third method is the actual lazy-loading code. We’re cheating a little here, using the
TreeNode.Checkedproperty to delineate whether or not the child nodes have already been loaded so we don’t do any unnecessary reloads. I always do this when I implement lazy-loaded trees because, in my experience, I almost never use theTreeNode.Checkedproperty. However, if you do need to use this property for something else, you can either use a different property (likeTag), create another dictionary to hold the expanded states, or modify the existing dictionary to hold a composite class (containing theIHierarchyDataas well as anExpandedproperty). I’m keeping it simple for now.The rest should already make sense to you if you’ve implemented lazy-loading in a tree before, so let’s skip ahead. Really the only thing left to do at this point is implement some designer/user properties that will actually wire up the tree and data:
Easy peasy. We’ve got a
DataSourceproperty that accepts the rootIHierarchyData, and aTreeViewproperty which you’ll be able to access from the designer. Again, simple stuff here, when theDataSourceproperty is updated, we just reset the lookup and repopulate the root. When theTreeViewproperty is updated we have to do a little more work, registering the events, making sure to unregister events from the old tree view, and doing all the same stuff we do when the data source changes.That’s really all there is to it! Open up the Windows Forms designer, drop a
TreeView, then drop aTreeViewHierarchyBindingand set itsTreeViewproperty to the tree view you just dropped. Finally, in your code somewhere (i.e. in theForm_Loadevent), give it a data source:(Note – this uses the example
FileSystemHierarchyDatathat’s on the MSDN page for IHierarchyData. The example isn’t very robust, it doesn’t check forUnauthorizedAccessExceptionor anything, but it’s good enough to demonstrate this).And that’s it. Run your app and watch it bind. You can now reuse the
TreeViewHierarchyBindingcomponent anywhere – just drop it on a form, assign it aTreeView, and give it anIHierarchyDatainstance as a data source.I’ve put the complete code on PasteBin if you want a copy-and-paste version.
Have fun!