Hierarchical Treeview with ASP.NET MVC & jQuery

Tuesday, November 25, 2008

First of all, an apology for being so quiet over the past few weeks.  I’ve been putting my blogging aside for a while to chase some pet projects I’m working on.  More on that later.

I did, however, run into a particular situation that I thought would be of interest to anyone adopting ASP.NET MVC and looking for some goodies from jQuery.  Many of you have no doubt started testing the waters with jQuery since it was announced that Microsoft will be shipping the next version of .NET with it included.  If you haven’t used jQuery yet, prepare to fall in love!  

In this post, I’m going to cover a simple way to build a deep, hierarchical and feature-rich tree structure with only one line of jQuery script.  jQuery has a huge library of plugins covering all sorts of functionality.  For this, we’ll be using a neat plugin from for treeviews.  Here’s what you need:
jQuery Treeview Plugin

This structure will consist of a category/sub-category relationship that is able to support n-levels of sub-categories with no changes.  To demonstrate, let’s look at the SQL table that supports the structure.

Notice the rows with ParentCategoryID set to NULL are the parent categories.  Each row with a ParentCategoryID is a sub-category and relates to it’s parent category.  The numbers show the level in outline view.

The jQuery Treeview plug-in requires the resulting HTML to be in a particular unordered list (<ul>) element to parse the tree correctly.  Since we don’t know how many levels to expect, we are going to call the MVC user control that renders each node recursively.  This control accepts a single Category item. 


We render the name of that category and then check if it has any categories associated with it.  If it does, we recursively render the control again.

In the controller, we are simply passing in the categories where the ParentCategoryID == null.


On the host view (Index.aspx), we create the root unordered list with an ID of “treeview” and pass in an array of the Parent categories (categories where the ParentCategoryID == null) from the controller. 


Here’s a look at the output WITHOUT the jQuery magic.

Now all we have to do is add the libraries we’re going to use and hook up the Treeview plugin.

Note:  I always use the jQuery script from the Google API’s.  By referencing it from Google’s server, you get to ride along their CDN, compression, etc. capabilities.  As an added bonus, if your user has already visited a site that referenced the same library, the jQuery library would be cached on their browser so they don’t take the hit of having to download it again.  Sweet!

In our jQuery script, we just get the ul’s element ID and call the plugin’s treeview() method with no options. 


When we refresh the page, we see jQuery has done its magic and now we have collapsable, rich tree view.

There’s a ton more options in the Treeview plugin that you can check out for yourself, including async loading with ajax, and tons of customizations.  ASP.NET MVC and jQuery – a match made in heaven!

Hope this helps!


  1. http:// says:

    Great article, thanks. If you allow me one little criticism, please start using GIF or PNG instead of JPG for the code screenshots, it gets a bit hard to read with all the artifacts.

  2. Mike Hadlow says:

    Very nice. I did the same thing a while back with an HtmlHelper extension. So you can write:

    < %= Html.RenderTree(ViewData.Model.CompositeThings, thing => thing.Name) %>

    The post is here:


  3. Good article, Mike.
    It would be nice if you can share code of that sample with us.

  4. Mike,

    My previous comment is unnecessary – entire code can be seen from screenshots.
    Sorry for that


  5. http:// says:

    demo,I want the demo!

  6. MikeBosch says:


    I suppose you’re talking about getting the source code? I guarantee all the code necessary is demoed above, but I’ll zip it up and attach it here in the next couple of days for ya. Thanks!

  7. http:// says:

    Can you please upload the code!
    For the first I can´t see the link to google jquery in your picture when its cutted to the right.
    And your database code can´t work. You just call the table where parentid is null. Where in the code do you get the other categories????

  8. http:// says:


    Do you mind sharing how your data model looked like?


  9. http:// says:

    Hey can u send some code on how to create

    1. 3 – level hierarchy grid in mvc

    2. How to right click on a grid row in mvc

    3. How to single click on a grid row in mvc

  10. http:// says:

    mike, to get categories in items u need to make a relation to categories table its self, the relation would be category->categoryid = category->parentCategory, once u have this in place(database) u can use linq to query like above.

  11. http:// says:

    thanks nice work.

    to get categories collection inside categories (item) you need to setup a relation between CategoryId and ParentCategoryId in the database.


    I don’t recomment this approch since it Recursivly execute database query. instead i would recomment the following changes ..

    ViewData[AllCategories] = dc.Categories.ToList();
    View(ViewData[AllCategories].Where(c=>c.ParentCategoryId == null));

    < %foreach (var item in ViewData.Model) {%>

  12. < %= item.CategoryText %>
    < % var children = ViewData[AllCategories].Where(c=>c.ParentCategoryId == item.CategoryId);%>
    < % if (children.Count() > 0) {%>

      < %Html.RenderPartial("~/Views/Shared/ItemControl.ascx", children);%>

    < % }%>

  13. < %}%>

    no need to change other stuff.

  • MikeBosch says:

    @atmonline great tip! It wasn’t until after that I noticed the 100′s of queries I was executing using SQL profiler. Linq to Sql is great but it makes it too easy to make mistakes like this! I messed with your example and it works great. Thanks!

  • Camcorder says:

    I’ts great that you show us this but we need the code to.

  • http:// says:

    NEVER use JPG format for screenshots. It’s big and ugly. Please use PNG instead.

  • jjroman says:

    Hi guys
    Can someone say me how to get this control working without specified particular value type? At now my solution to get this code working is to change first line of ASCX file to:
    and foreach statement to:
    foreach(var item in (IEnumerable)ViewData.Model)

    Is it possible to reach the same effect using ADO.net Entity data objects without copying all data into some kind of hashtables?
    when I try to make list.Where(p=>p.ParentsRelation.IdParent == item.IdCategory); I get null pointer exception :(

  • http:// says:

    I don’t think you need to specify the ~/Views/Shared.
    MVC automatically looks there (after looking in the controller’s View directory.

    I just do this:


  • I like this post very much i will use this tree view on my site.

  • http:// says:

    It is really wast our time, the simple idea is to put you code packed and downloadable. Then we are sure your code is clear and right.

  • daniel says:

    can this code be downloaded?

    and what should be done if you what to load the children async?

  • http:// says:

    Please upload you demo project, we can use and test quickly.

  • http:// says:

    It works but when having nodes more than ten thounsands it reponse very slow

  • http:// says:


    I am new to MVC and i am trying to get this to work but haveing problems, can somebody direct me to the source code for this mini app?



  • http:// says:

    I am new to asp.net MVC.

    I want to ceate treeview at dynamically with user input. User should be able to ceate root, parant and child node. User should be able to add , edit or delete nodes.


  • http:// says:

    Can we please get the entire project? I’m new to MVC and would really like to use this

  • http:// says:

    can u share me your project?thanks!

  • Andrey says:

    Thanks! Oh, where is it source? Please please please.

  • James says:

    I’m new to MVC and having some difficulties with the treeview. Can you share a sample project with me?

    Thank you!

  • Alex Leblois says:

    This is very informative article. Thanks for sharing with us.

  • Leave a Reply