This is a migrated thread and some comments may be shown as answers.

Populating RadTreeView from flat object structure

7 Answers 250 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
hwsoderlund
Top achievements
Rank 1
hwsoderlund asked on 19 Jun 2008, 06:52 AM
I have a flat object structure where the hierarchy is defined through ID -> ParentID relations. In RadTreeView for asp.net it is possible to bind such a structure to the tree by setting the DataFieldParentID property on the treeview object. Is it possible to bind the RadTreeView for silverlight against this type of structure? /Henrik

7 Answers, 1 is accepted

Sort by
0
Valentin.Stoychev
Telerik team
answered on 20 Jun 2008, 08:25 AM
Hi Henrik,

we do not support the DataFieldParentID property. You have to convert the flat structure to hierarchical one and them to give it as an ItemsSource to the Treeview. You can do that easily using LINQ.

How important is having implemented the DataFieldParentID functionality for our hierarchical controls. Isn't it better to use LINQ to convert the list to hierarchical structure?

Best wishes,
Valentin.Stoychev
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Michael
Top achievements
Rank 1
answered on 20 Jun 2008, 10:47 PM
I am curious about this suggestion.
I looked around for quite a while and have not come up with a solution myself.
By chance can you provide a snippet of code that shows the use your Tree and the LINQ statements?  (Do we need IHierarchyData - and a custom class for our data?).
I am using vb.net (but can usually convert any C#).

-Michael
0
hwsoderlund
Top achievements
Rank 1
answered on 23 Jun 2008, 07:41 AM
Valentin: It's not hugely important, as you said it can be done quite easily with LINQ. I came up with the following code, but it's annoying having to use recursion. I'm sure LINQ has better ways of converting to hierarchical data. If you have a better example, please post it.

Just to explain the code below, the class DomainListEntity is my self-referencing table. I constructed the class DomainHierarchy as a placeholder, and the recursive method GetDomainsHierarchy converts my original list to a hierarchy using LINQ.

public class DomainHierarchy

{

    public DomainListEntity Domain { get; set; }

    public List<DomainHierarchy> Children { get; set; }

}


public List<DomainHierarchy> GetDomainsHierarchy(List<DomainListEntity> allDomains, DomainListEntity parentDomain)

{

    int? parentDomainId = null;

 

    if (parentDomain != null)

        parentDomainId = parentDomain.DomainID;

 

    var childDomains = allDomains.Where(d => d.ParentID == parentDomainId);

 

    List<DomainHierarchy> hierarchy = new List<DomainHierarchy>();

 

    foreach (var domain in childDomains)

        hierarchy.Add(new DomainHierarchy() { Domain = domain, Children = GetDomainsHierarchy(allDomains, domain) });

 

    return hierarchy;

 

}

0
Miroslav
Telerik team
answered on 25 Jun 2008, 08:27 AM
Hello Henrik,

Thanks for bringing up the very interesting question about how to convert a flat list structure to a hierarchy. The Recursive method probably is not the best option since a deeper hierarchy can result in a large callstack that can lead us into trouble.

So it's time for examples :)

Let us say we have the following flat structure:
public class FlatDataItem  
    {  
        public int Id  
        {  
            get;  
            set;  
        }  
 
        public int ParentId  
        {  
            get;  
            set;  
        }  
 
        public String Name  
        {  
            get;  
            set;  
        }  
    } 

And we want to convert it to the following:

public class HierarchicalDataItem  
    {  
        public List<HierarchicalDataItem> Children  
        {  
            get;  
            set;  
        }  
        public String Name  
        {  
            get;  
            set;  
        }  
        public int Id  
        {  
            get;  
            set;  
        }  
        public int ParentId  
        {  
            get;  
            set;  
        }  
    } 

1. Iteration:

We can use an iterative method:

Dictionary<int, HierarchicalDataItem> hierarchialData = new Dictionary<int,HierarchicalDataItem>(flatItemsSource.Count+1);  
 
            //Create a dictionary of hierarchical items.  
            foreach (var flatItem in flatItemsSource)  
            {  
                hierarchialData.Add(flatItem.Id, new HierarchicalDataItem()  
                {  
                    Name = flatItem.Name,  
                    Id = flatItem.Id,  
                    ParentId = flatItem.ParentId,  
                    Children = new List<HierarchicalDataItem>()  
                });  
            }  
            //Add each item to its parent  
            foreach (var hierachialItem in hierarchialData.Values)  
            {  
                if (hierachialItem.ParentId == 0)  
                {  
                    continue;  
                }  
 
                hierarchialData[hierachialItem.ParentId].Children.Add(hierachialItem);  
            }  
            //Find the roots:  
            List<HierarchicalDataItem> roots = hierarchialData.Values.Where(item => item.ParentId == 0).ToList(); 

What we are doing here is creating a dictionary (still a flat structure) so that we can easily find an item by its id. Then each item is added to the list of children of its parent.

To get the root items, we search for the items with parent id == 0.

2. LINQ:

There is always the question of when to use LINQ. It surely is faster in some deferred loading scenarios and is more readable in others. But is it better for this? Here is the code:

            //Create a flat list of hierarchical items:  
            var hierarchicalList = flatItemsSource.Select(flatItem =>  
                new HierarchicalDataItem()  
                {  
                    Name = flatItem.Name,  
                    Id = flatItem.Id,  
                    ParentId = flatItem.ParentId  
                }).ToList();  
 
            //Join the items from the list with groups of items from the same list and select the roots.  
            //i.e. join each parent with its children.  
            var theRoots = hierarchicalList.GroupJoin(hierarchicalList,   
                parentItem => parentItem.Id,   
                childItem => childItem.ParentId,   
                (parent, children) =>  
                    {  
                        parent.Children = children.ToList();  
                        return parent;  
                    }).Where(item => item.ParentId == 0).ToList() ; 

I prefer the extension methods but you can easily translate this to the keywords-style linq. The magic here is in the group join. This method allows us to join an object with a collection of objects, in our case the parent with its children.

The parameters of the join are: the list from which we will take the objects to join (i.e. the children, which is the same as the list of the parents). Then we have to give a selector function for the key of the parent on which they will be joined. Then a key (that is of the same type, int in our case) that will select the children for the parent and an optional function that will do the joining.

I normally would prefer Linq to any other selection method but in this particular case the iteration looks much better.

Which one do you like best?

Unfortunately I could not find a large hierarchical data set to test the performance. Do you have data that you can test it on? Which one is faster and which one has a smaller memory footprint? That will be quite interesting!

As an attachment you can find the small test project that I created.

Regards,
Miroslav
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
hwsoderlund
Top achievements
Rank 1
answered on 25 Jun 2008, 01:47 PM
Thanks for the example, I'll try and test it with a larger data set and see which is more efficient. Even though the LINQ method is sweet I think I prefer the iterative method. It's much more readable.
0
Elton
Top achievements
Rank 1
answered on 26 Jun 2008, 05:44 AM

Hi Miroslav

I tried your linq method. However it doestn't work.

From RadTreeView's document, it says that

Any class that implements the IEnumerable interface can not create treeview item hierarchy. 
http://www.telerik.com/help/aspnet/treeview/tree_databinding_overview.html

In my case, I can not use any one of 
  • DataTable, DataSet, DataView
  • SiteMapDataSource
  • XmlDataSource
  • SqlDataSource
  • AccessDataSource
  • What i have is a ISingleResult<>?

    Is there a way to generate a hierachical treeview?

    Best Regards
    Geoffrey

    0
    hwsoderlund
    Top achievements
    Rank 1
    answered on 27 Jun 2008, 11:53 AM
    Miroslavs example only applies to the Silverlight tree component, not the asp.net version.
    Tags
    General Discussions
    Asked by
    hwsoderlund
    Top achievements
    Rank 1
    Answers by
    Valentin.Stoychev
    Telerik team
    Michael
    Top achievements
    Rank 1
    hwsoderlund
    Top achievements
    Rank 1
    Miroslav
    Telerik team
    Elton
    Top achievements
    Rank 1
    Share this question
    or