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

How to build multi level hierarchy with unknown levels?

9 Answers 923 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Robert
Top achievements
Rank 1
Robert asked on 23 Apr 2012, 01:48 AM
Hi,

I'm having difficulty trying to build a multi level hierarchy that has unknown levels.
I've read loads and loads of examples but they all assume the number of levels are known. However, in my case I may have "x" number of nodes, which may have "x" number of child nodes, which may have "x" number of grandchild nodes etc etc.

My data is drawn from an SQL database where I use the SQL 2008 HierarchyID data type to represent my hierarchy in the database.

I've built the following class for my products:



public class Products : INotifyPropertyChanged, IDataErrorInfo
{
private Int64 m_ID;
private SqlHierarchyId m_Hierarchy;
private string m_Name;
private Int16 m_Level;
private ObservableCollection<Products> m_ChildProducts;
// Default Constructor
public Products()
{
ChildProducts = new ObservableCollection<Products>();
}
//Properties
public Int64 ID
{
get
{
return m_ID;
}
set
{
m_ID = value;
OnPropertyChanged(new PropertyChangedEventArgs("ID"));
}
}
public SqlHierarchyId Hierarchy
{
get
{
return m_Hierarchy;
}
set
{
m_Hierarchy = value;
OnPropertyChanged(new PropertyChangedEventArgs("Hierarchy"));
}
}
public Int16 Level
{
get
{
return m_Level;
}
set
{
m_Level = value;
OnPropertyChanged(new PropertyChangedEventArgs("Level"));
}
}
public String Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
public ObservableCollection<Products> ChildProducts
{
get
{
return m_ChildProducts;
}
set
{
m_ChildProducts = value;
OnPropertyChanged(new PropertyChangedEventArgs("ChildProducts"));
}
}
//INotifyPropertyChanged Event
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}


I then have the following method to download data from the database which I need to some how construct an ObservableCollection() which contains nodes "x" number of levels deep. Please note that some nodes may be 2 levels deep, others may be 3 levels deep, so forth and so forth.


public static ObservableCollection<Products> GetProductsHierarchy()
        {
            ObservableCollection<Products> products = new ObservableCollection<Products>();
 
            SqlConnection connection = new SqlConnection(DBConnection.GetConnection().ConnectionString);
 
            string selectStatement = "SELECT ID, Hierarchy, Name " +
                                     "FROM SpecProducts " +
                                     "WHERE (EnableDisable IS NULL)" +
                                     "ORDER BY Hierarchy";
 
            SqlCommand selectCommand = new SqlCommand(selectStatement, connection);
 
            try
            {
                connection.Open();
                SqlDataReader reader = selectCommand.ExecuteReader();
 
                while (reader.Read())
                {
                     
                    Products product = new Products();
                    product.ID = (Int64)reader["ID"];
                    product.Name = reader["Name"].ToString();
                    product.Hierarchy = (SqlHierarchyId)reader["Hierarchy"];
                    product.Level = (Int16)product.Hierarchy.GetLevel();
 
                    //**** How to create recursive loop to add unknown levels to nodes???? ****
 
                    products.Add(product);
                }
 
 
                return products;
            }
            catch (SqlException ex)
            {
                throw ex;
            }
            finally
            {
                connection.Close();
            }
        }


I've found a post that discusses unlimited nodes, http://www.telerik.com/community/forums/wpf/treeview/templated-node-multiple-parent.aspx , but in the example given it has the following lines of code to build up unlimited levels:
ObservableCollection<Node> nodes = new ObservableCollection<Node>();
 
nodes.Add(new Node("Company"));
nodes[0].Nodes.Add(new Node("Department"));
nodes[0].Nodes[0].Nodes.Add(new Node("here are you"));
nodes[0].Nodes[0].Nodes[0].Nodes.Add(new Node("even deeper"));
 
radTreeView1.ItemsSource = nodes;

Surely this is only valid providing you know the number of levels before runtime?


I guess I'm essentially looking for a generic hierarchy builder where the number of levels are unknown until runtime, i.e. when data is download from database.

Any help would be greatly appreciated.

Thanks for your time.


9 Answers, 1 is accepted

Sort by
0
Petar Mladenov
Telerik team
answered on 25 Apr 2012, 07:21 AM
Hi Robert,

 The way to prepare your RadTreeView for unknown hierarchy levels is to prepare well your ViewModels. If your DB objects cannot satisfy the following requirements, you can create a ViewModel wrapper classes to wrap your DB entities.
So if your ViewModels have child Collection called "Children" and you want common Template you just have to use one HierarchicalDatatemplate definition:

<telerik:HierarchicalDataTemplate x:Key="itemtemplate" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}"  />
</telerik:HierarchicalDataTemplate>
<telerik:RadTreeView ItemTemplate="{StaticReSource itemtemplate}" ...
This way you can have unknown number of hierarchy levels. Every level will automatically use this template and will provide "Children" child collection.
If your ViewModels are different types you have to make them inherit from one base type and use TemplateSelectors - if A item is given - use ATemplate, if B item is given - use BTemplate but A and B must inherit from one base type. You can check the attached project where similar approach is realized.
(It is an SL solution, but the same technique could be used for WPF).
Please let us know if you need further assistance on this. Regards,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Robert
Top achievements
Rank 1
answered on 26 Apr 2012, 02:31 AM
Hi,

thank you for your response. For some reason I am unable to download your zip file example. When I click the download link I'm presented with a blank screen and nothing happens.
0
Petar Mladenov
Telerik team
answered on 26 Apr 2012, 09:29 AM
Hi Robert,

I am attaching the file again. Could you please try to download it again? If the issue is still reproducible, could you please test this with different browsers ? Is it possible for you to send us a captured video ? Thank you in advance.

Kind regards,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Robert
Top achievements
Rank 1
answered on 26 Apr 2012, 10:25 AM
Hi,

Thanks for trying to repost it. Unfortunately this link also doesn't work.
I've tried it with IE9 32bit & 64bit browsers. I currently don't have another browser installed on my PC. I will have to try someone elses computer when I get a chance and I don't have any screen capture software. Can you recommend any screen capture packages?
0
Robert
Top achievements
Rank 1
answered on 26 Apr 2012, 01:28 PM
Here's a more in depth forum post to my problem http://stackoverflow.com/questions/10300273/how-to-build-object-hierarchy-from-sql-query-for-wpf-treeview

However this isn't the complete solution. For some reason it only works to two node levels deep.
0
Robert
Top achievements
Rank 1
answered on 26 Apr 2012, 02:26 PM
I've uploaded my treeview code project to the internet. It only contains the treeview code.
Can someone please take a look at it for me? For some reason it will only generate nodes 2 levels deep.
You can see how it works by looking at the MainWindow Loadoad Method.
This is WPF c# .net 4 with the latest telerik libraries.

Click here to download the file

Thank you very much for your time. All help is appreciated.
0
Robert
Top achievements
Rank 1
answered on 26 Apr 2012, 07:55 PM
I have managed to solve it but programmatically, i.e. not via binding.

You can download my source code here.

I'm still all ears if someone can find a solution using bindings for my example.
0
Petar Mladenov
Telerik team
answered on 27 Apr 2012, 02:19 PM
Hi Robert,

 Similar project to the one I attached here is also attached in this forum post. You can also check a good "TreeView bound to self-referencing table" Solution in this thread. Hope you will find them useful.

Kind regards,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Ammar
Top achievements
Rank 1
answered on 11 Dec 2018, 07:45 AM
Solution provided by Petar Mladenov worked for me.
Tags
TreeView
Asked by
Robert
Top achievements
Rank 1
Answers by
Petar Mladenov
Telerik team
Robert
Top achievements
Rank 1
Ammar
Top achievements
Rank 1
Share this question
or