Populating RadTreeView from flat object structure

8 posts, 0 answers
  1. hwsoderlund
    hwsoderlund avatar
    419 posts
    Member since:
    Aug 2006

    Posted 19 Jun 2008 Link to this post

    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
  2. Valentin.Stoychev
    Admin
    Valentin.Stoychev avatar
    2198 posts

    Posted 20 Jun 2008 Link to this post

    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
  3. DevCraft banner
  4. Michael
    Michael avatar
    3 posts
    Member since:
    Nov 2007

    Posted 20 Jun 2008 Link to this post

    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
  5. hwsoderlund
    hwsoderlund avatar
    419 posts
    Member since:
    Aug 2006

    Posted 23 Jun 2008 Link to this post

    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;

     

    }

  6. Miroslav
    Admin
    Miroslav avatar
    922 posts

    Posted 25 Jun 2008 Link to this post

    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:

    1 Dictionary<int, HierarchicalDataItem> hierarchialData = new Dictionary<int,HierarchicalDataItem>(flatItemsSource.Count+1);  
    2  
    3             //Create a dictionary of hierarchical items.  
    4             foreach (var flatItem in flatItemsSource)  
    5             {  
    6                 hierarchialData.Add(flatItem.Id, new HierarchicalDataItem()  
    7                 {  
    8                     Name = flatItem.Name,  
    9                     Id = flatItem.Id,  
    10                     ParentId = flatItem.ParentId,  
    11                     Children = new List<HierarchicalDataItem>()  
    12                 });  
    13             }  
    14             //Add each item to its parent  
    15             foreach (var hierachialItem in hierarchialData.Values)  
    16             {  
    17                 if (hierachialItem.ParentId == 0)  
    18                 {  
    19                     continue;  
    20                 }  
    21  
    22                 hierarchialData[hierachialItem.ParentId].Children.Add(hierachialItem);  
    23             }  
    24             //Find the roots:  
    25             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:

    1             //Create a flat list of hierarchical items:  
    2             var hierarchicalList = flatItemsSource.Select(flatItem =>  
    3                 new HierarchicalDataItem()  
    4                 {  
    5                     Name = flatItem.Name,  
    6                     Id = flatItem.Id,  
    7                     ParentId = flatItem.ParentId  
    8                 }).ToList();  
    9  
    10             //Join the items from the list with groups of items from the same list and select the roots.  
    11             //i.e. join each parent with its children.  
    12             var theRoots = hierarchicalList.GroupJoin(hierarchicalList,   
    13                 parentItem => parentItem.Id,   
    14                 childItem => childItem.ParentId,   
    15                 (parent, children) =>  
    16                     {  
    17                         parent.Children = children.ToList();  
    18                         return parent;  
    19                     }).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
  7. hwsoderlund
    hwsoderlund avatar
    419 posts
    Member since:
    Aug 2006

    Posted 25 Jun 2008 Link to this post

    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.
  8. Elton
    Elton avatar
    98 posts
    Member since:
    Oct 2007

    Posted 26 Jun 2008 Link to this post


    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 
  9. DataTable, DataSet, DataView
  10. SiteMapDataSource
  11. XmlDataSource
  12. SqlDataSource
  13. AccessDataSource
  14. What i have is a ISingleResult<>?

    Is there a way to generate a hierachical treeview?

    Best Regards
    Geoffrey

  • hwsoderlund
    hwsoderlund avatar
    419 posts
    Member since:
    Aug 2006

    Posted 27 Jun 2008 Link to this post

    Miroslavs example only applies to the Silverlight tree component, not the asp.net version.
  • Back to Top
    DevCraft banner