Click here to Skip to main content
15,867,568 members
Articles / Web Development / ASP.NET
Article

Implementing IHierarchy Support Into Your Custom Collections

Rate me:
Please Sign up or sign in to vote.
4.85/5 (25 votes)
17 Jul 20073 min read 157.5K   1.9K   67   41
Brief walk-through on decorating your custom collections with the IHierarchy family of interfaces to support databinding.

Screenshot of the final output.

Introduction

This quick tutorial will hit on the major features of the IHierarchicalDataSource provided by ASP.NET 2.0. Throughout I take a common set of data (a storefront listing of categories) in the form of a strongly typed generic list and entity and bind it together using the IHierarchy family of interfaces demonstrating how to turn any custom collection into a useful data binding tool.

Background

Displaying hierarchical data on the web is not a simple task, as you may already know if you have ever tried to bind a custom collection of hierarchical data to a standard ASP.NET TreeView control. No matter what the original shape of the data is, it is quite a pain to loop through and bind using the AddNode methods provided. You have to recursively look up the parent controls, ensure your data is sorted, etc. Overall it is a pretty big pain in the [Insert Bleep Here]! Hopefully after reviewing the following, you will find it much easier to extend your custom collections with this technology and remove all your nested data headaches!

Enjoy!

Using the code

I have tried to package this up as seamless as possible. Open'er up in Visual Studio 2005 and you should have a file path ASP.NET Web Site. I have one file for each class object (I guess that is the "team developer" in me) and a static method in the common class for quick sample data tucked nicely into a strongly typed generic list implementation.

Viewing the Default.aspx page should yield a tree view of a computer store product category TreeView demonstrating the code below.

On with the show...

To start with, we need a basic entity and collection, mine looks similar to this:

C#
using System;
using System.Collections.Generic;

public class Category {

   private int _categoryId;
   private int _parentId;
   private string _name;
   
   public int CategoryId {
      get { return _categoryId; }
      set { _categoryId = value; }
   }
   
   public int ParentId {
      get { return _parentId; }
      set { _parentId = value; }
   }
   public string Name {
      get { return _name; }
      set { _name = value; }
   }

   public Category(int categoryId, int parentId, string name) {
      _categoryId = categoryId;
      _parentId = parentId;
      _name = name;
   }   
}

public class CategoryCollection : List<Category> {

   public CategoryCollection()
      : base() {
   }
}

Implementing IHierarchyData on the Entity

In order to tell the CLR that your collection has hierarchical data, it in fact must be! Let's add that by adding the System.Web.UI namespace along with implementing the IHierarchyData interface and its required members as shown here:

C#
using System;
using System.Collections.Generic;
using System.Web.UI;

public class Category : IHierarchyData {
   ...

   #region IHierarchyData Members

   // Gets an enumeration object that represents all the child 
   // nodes of the current hierarchical node.
   public IHierarchicalEnumerable GetChildren() {

      // Call to the local cache for the data
      CategoryCollection children = new CategoryCollection();

      // Loop through your local data and find any children
      foreach (Category category in Common.GetCategoryData()) {
         if (category.ParentId == this.CategoryId) {
            children.Add(category);
         }
      }

      return children;
   }

   // Gets an IHierarchyData object that represents the parent node 
   // of the current hierarchical node.
   public IHierarchyData GetParent() {
      
      // Loop through your local data and report back with the parent
      foreach (Category category in Common.GetCategoryData()) {
         if (category.CategoryId == this.ParentId)
            return category;
      }

      return null;

   }

   public bool HasChildren {
      get {
         CategoryCollection children = GetChildren() as CategoryCollection;
         return children.Count > 0;
      }
   }

   // Gets the hierarchical data node that the object represents.
   public object Item {
      get { return this; }
   }

   // Gets the hierarchical path of the node.
   public string Path {
      get { return this.CategoryId.ToString(); }
   }

   public string Type {
      get { return this.GetType().ToString(); }
   }

   #endregion   
}

The GetChildren() and GetParent() methods are where the magic really takes place. These two internal methods power the hierarchy definition and allow the controls to link them appropriately.

Implementing IHierarchicalEnumerable on the Collection

For the code immediately above to work, the method GetChildren() is counting on us handing back an implementation of IHierarchicalEnumerable.

Implementing this interface is a simple task of coding one method (GetHierarchyData()) that will ensure proper object typing within the collection as shown below:

C#
public class CategoryCollection : List<Category>, IHierarchicalEnumerable {
   ...
   
   #region IHierarchicalEnumerable Members

   // Returns a hierarchical data item for the specified enumerated item.
   public IHierarchyData GetHierarchyData(object enumeratedItem) {
      return enumeratedItem as IHierarchyData;
   }

   #endregion
}

Finally... Some Output!

To see the results, simply create a new ASPX page and add a ASP:TreeView control to it. In code-behind, the following snippets will bind the results from your newly decorated collection to the tree view and organize it within the hierarchy you defined.

C#
ASP.Net
----------------------------------------------------------
<asp:TreeView ID="uxTreeView" runat="server" />

Code Behind
----------------------------------------------------------
protected void Page_Load(object sender, EventArgs e) {

   if (!IsPostBack) {
            
      // Local cache of category data
      CategoryCollection collection = Common.GetRootCategories();

      // Bind the data source to your collection
      uxTreeView.DataSource = collection;
      uxTreeView.DataBind();
   }
}

Now that your collection and entity are all hyped-up on interfaces, you can use them again and again on hierarchy displaying controls natively.

Points of Interest

If anyone can answer the question as to why this is hidden away in the System.Web.UI namespace, I would love to hear it! I cannot imagine this having "web only" requirements, but I have not yet tried it in a Windows application.

In the code download, I have also included an implementation of IHierarchicalDataSource and HierarchicalDataSourceView for those of you who prefer to declaratively bind the data on the ASPX side with DataSource controls.

History

  • Wednesday, July 18, 2007 - Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Scott Piegdon works full time as a Director of Quality Control for a software development company specializing Credit Union Member Services. He has experience as a Vice President of Information Technologies for a hosted ERP (Enterprise Resource Planning) company. He also runs a Web Design Services company (http://www.simplifyitwebdesign.com). He has a beautiful and wonderful wife, and two fantastic children. He loves to develop applications that others find not only easy to use and pleasing to the eye, but also provide un-surpassing functionality. He has been developing websites for over 12 years, and programming professionally for 9 of them. He has worked with dozens of database, scripting, procedural and compiled languages over the years, most recently specializing in Microsoft.Net C# 2.0 with ASP.Net backed by SQL Server 2005.

"Hopefully I can pass along some of the insight and knowledge I have acquired over the years to those curious enough to read it." - Scott Piegdon

Comments and Discussions

 
QuestionAdding a string value to say .Tooltip property Pin
xav207511-Mar-14 17:24
xav207511-Mar-14 17:24 
QuestionStore more data on the treenode Pin
noobville20-May-13 8:43
noobville20-May-13 8:43 
GeneralI have similar article without IHierarchyData interface Pin
santosh poojari30-Dec-10 17:28
santosh poojari30-Dec-10 17:28 
GeneralNice article Pin
darren_106510-Feb-09 18:27
darren_106510-Feb-09 18:27 
Generalchange Pin
248912811-Nov-08 22:02
248912811-Nov-08 22:02 
Generalnote using shared data source Pin
gregmoyer6-Oct-08 7:06
gregmoyer6-Oct-08 7:06 
GeneralExcellent Article Pin
eraghi22-Sep-08 12:18
eraghi22-Sep-08 12:18 
GeneralRe: Excellent Article Pin
spiegdon22-Sep-08 13:12
spiegdon22-Sep-08 13:12 
GeneralExtending to HierarchicalSqlDataSource Pin
Andersoc24-Apr-08 1:22
Andersoc24-Apr-08 1:22 
GeneralYa butt ... Pin
mike.griffin@entityspaces.net5-Nov-07 14:41
mike.griffin@entityspaces.net5-Nov-07 14:41 
GeneralRe: Ya butt ... Pin
spiegdon17-Nov-07 16:39
spiegdon17-Nov-07 16:39 
GeneralThanks! Pin
Summer_son3-Nov-07 8:36
Summer_son3-Nov-07 8:36 
GeneralSQL DB DataSource Pin
jeffb4230-Aug-07 13:51
jeffb4230-Aug-07 13:51 
GeneralRe: SQL DB DataSource Pin
spiegdon30-Aug-07 17:08
spiegdon30-Aug-07 17:08 
AnswerRe: SQL DB DataSource Pin
spiegdon27-Nov-07 13:58
spiegdon27-Nov-07 13:58 
QuestionHow to set up the files Pin
andrewward13-Aug-07 2:27
andrewward13-Aug-07 2:27 
I am someone who likes to see how it works and then sort through the code. I have put the files into a directory. Created a new web site in VS2005 and then added the files to the project solution. I have then tried building the solution and running it with Default.aspx as the start page. However, I get an error that there is an "Unknown server tag 'HierarchyExample:CategoryDataSource'" on Default.aspx and that "using HierarchyExample;" is not recognised in Default.aspx.cs.

Any suggestions on what I am doing wrong (all the .cs files are in the "App_Data" directory as part of the solution)?

AnswerRe: How to set up the files Pin
rodchar16-Aug-07 2:56
rodchar16-Aug-07 2:56 
GeneralRe: How to set up the files Pin
andrewward17-Aug-07 3:10
andrewward17-Aug-07 3:10 
GeneralRe: How to set up the files Pin
spiegdon30-Aug-07 17:10
spiegdon30-Aug-07 17:10 
GeneralWithDataSource Possible issue Pin
rodchar8-Aug-07 9:05
rodchar8-Aug-07 9:05 
GeneralRe: WithDataSource Possible issue Pin
spiegdon30-Aug-07 17:08
spiegdon30-Aug-07 17:08 
GeneralRe: WithDataSource Possible issue Pin
Andersoc23-Apr-08 5:48
Andersoc23-Apr-08 5:48 
GeneralRe: WithDataSource Possible issue Pin
Andersoc23-Apr-08 6:23
Andersoc23-Apr-08 6:23 
Generalorganizational chart Pin
rodchar6-Aug-07 9:02
rodchar6-Aug-07 9:02 
GeneralRe: organizational chart Pin
spiegdon6-Aug-07 12:36
spiegdon6-Aug-07 12:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.