views:

753

answers:

5

I have 5 tables in a L2S Classes dbml : Global >> Categories >> Sub-Category >> Item >> Item Data. I want to be able to navigate from the Global table down a tree like structure to get to the items - displaying the title from the Item Data table.

I have an existing control that uses a IHierarchyData / IHierarchicalEnumerable extended collection by iterating over the collection to output an un-ordered list which I then turn into a tree with jquery. I did it based on Return Un-Ordered List from hierarchical sql data

Is there an easy generic way that I could use to put the data from the above table structure into a a Hierarchical structure so that I could re-use my existing control and and just pass in a different collection.

A: 

I think what is hanging you up is that you don't need four tables to do this.

Look at http://stackoverflow.com/questions/636943/return-unordered-list-from-hierarchical-sql-data again. There aren't four tables there. There's only one.

Robert Harvey
True and I implemented that solution for one tree where I have self-referencing data just like that solutions "Page" table. For my problem I want another tree were I want to basically drill down through 4 seperate tables to get into the item.
Breadtruck
I edited the question to hopefully make it more clearer.
Breadtruck
A: 

You can use the Union operator to mash your four tables together. http://weblogs.asp.net/zeeshanhirani/archive/2008/04/11/union-operator-part-12.aspx

Robert Harvey
@Robert: Using that concept wouldn't I end up with items in the collection where the primaryID and parentID are overlapping so to speak? My global keys would be the same in some instances as the categories keys because each table in my structure uses an identity seed that started at 1?
Breadtruck
Well, we're back to a single-table design again then, unless you want to use GUIDs for your primary keys in each table.
Robert Harvey
I was able to do what I needed to do for this instance, I don't like the code and its not re-usable, I just thought there would be a way to take a table that has a child collection which in turn has another child collection and just use these collections to build some sort of structure that has a "Hierarchical" like feel to populate a tree/nested list.
Breadtruck
When you union the tables together, you need a column in the output that tells you which table is being referenced, i.e. the level of nesting. That's the only other way that I can think of.
Robert Harvey
You can also add a line number to the output to make the numbers unique, see http://stackoverflow.com/questions/365086/. But these numbers are arbitrary (they don't point to a record in any table), and wer're getting a little wrapped around the axle at this point.
Robert Harvey
A: 

Since I can't post a comment, breadtruck, did you ever figure this out? I have a similiar problem.

Matt
+1  A: 

Have you tried Nested Listviews? I have implemented this solution in several pages. I use ObjectDataSources instead of LinqDataSources directly to keep my data logic separate, but the nested EntitySets work beautifully.

pthalacker
A: 

Since you are dealing different types in this case, you will have to implement a common interface on each of them to make the code generic. The basic approach would be to create an interface that includes any needed properties (e.g. DisplayText, ActionURL, etc) then iterate over the collection recursively.

Here's a rough example:

 public interface IDataItem
    {
        string DisplayText { get; }
        string ActionUrl { get;  }
        bool HasChildren { get; }
        IEnumerable<IDataItem> GetChildren();
    }

 public void CreateTree(HtmlTextWriter writer, IEnumerable<IDataItem> collection)
    {
        writer.WriteFullBeginTag("ul");
        foreach (var data in collection)
        {
            writer.WriteFullBeginTag("li");
            writer.WriteBeginTag("a");
            writer.WriteAttribute("href",data.ActionUrl);
            writer.Write(HtmlTextWriter.TagRightChar);
            writer.Write(data.DisplayText);
            writer.WriteEndTag("a");
            if(data.HasChildren)
                CreateTree(writer, data.GetChildren());
            writer.WriteEndTag("li");
        }
        writer.WriteEndTag("ul");
    }

You will have to implement the interface on each of your types that you want included in the treeview. The just pass in the collection of the top level type and the method above will walk down the hierarchy creating the needed nested list.

Jeff French