In this example I will show you how to populate a RadTreeView using LINQ and WCF. Also you will see how to transform a flat data into a hierarchical one.

The target result is:

1. Create a new Silverlight Web Application Project

NOTE: Make sure you choose "Web Application Project"

After the project loads you can see that besides the regular Silverlight application, Visual Studio adds a Web application that will host the .xap file.

 

Before writing any LINQ or creating any WCF service, we need a database to target.

2. Right-click on RadTreeViewWithWCFWeb project and add a new item - "SQL Server Database". You can give the database any name you wish. I personally called mine TVSeries since this is going to be a TV related tutorial :).

Visual Studio will ask you whether you want to place the database in the App_Data folder. Click Yes to confirm.

Examine the RadTreeViewWithWCFWeb's App_Data folder and you will find your database there.

3. Double-clicking the TVSeries.mdf file will automatically send the database to the "Server Explorer" window.

It is now time to populate the database with some data. To keep the tutorial short, I will add only one table and fill it with data. I have called my table FoxTVSeries. You can download the database here.

Since the database is populated, it is time to do LINQ on it.

4. Right-click on RadTreeViewWithWCFWeb project and add a new item - "LINQ to SQL Classes".

5. Open the "Server Explorer" window and drag the FoxTVSeries table onto the "Object Relational Designer". ("Object Relational Designer" opens automatically when you open the DataClasses1.dbml file)

The "Object Relational Designer" will automatically show the columns that the table has.

6. By default, the LINQ class is not serializable. In order to use the table in a web service, we need to make the DataClasse1.dbml file serializable. Right-click on the design surface and choose Properties from the drop-down. In the properties window change the "Serialization Mode" to Unidirectional.

 

7. The LINQ is done, it is time now to create the web service. Again, right-click on RadTreeViewWithWCFWeb project and add a new item - "WCF Service".

Visual Studio adds 3 files that hold the service contract for the WCF service - IService1.cs, Service1.svc and a code-behind to it - Service1.svc.cs.

8. Open the first file - IService1.cs. This file contains the operation contract. Change the name and the signature of the DoWork() method - change its name to GetTVSerie and change its return value to be List<FoxTVSery>.

9. Go to the Service1.svc.cs file and implement the IService1 interface

10. Keeping the example as simple as possible, we will select all the the items in the table, without any grouping, ordering etc.

11. One thing that is important is to make sure that your web service uses a basicHttpBinding, not the default wsHttpBinding. Go to the Web.config file and scroll down until you find the system.serviceModel tag. Change the binding="wsHttpBinding" to binding="basicHttpBinding".

The reason to change the binding is because Silverlight supports only basic binding (SOAP 1.1 etc.).

Congrats, the web service is all set! The next step is to use the web service in the Silverlight application.

12. Go to the RadTreeViewWithWCF project, right-click on References and add a "Service Reference".

A popup window appears hit the Discover button  to find the web service and then hit OK to add it.

13. Once you have the WCF Service added, it is time work a little on the XAML and actually add the TreeView. First of all add references to Telerik.Windows.Controls.dll and Telerik.Windows.Controls.Navigation.dll.

14. Open the Page.xaml file and reference the previously added dlls. Also you need to reference the RadTreeViewWithWCF project.

15. In the UserControl.Resources of Page.xaml we have to create a hierarchical data template that will be used as an item template for the TreeView. Also we create the data source for the TreeView

 1: <UserControl.Resources>
 2:  
 3: <local:HierarchicalDataSource x:Key="Source" />
 4:  
 5: <core:HierarchicalDataTemplate x:Key="NodeTemplate" ItemsSource="{Binding Children}">
 6: <core:HierarchicalDataTemplate.HeaderTemplate>
 7: <DataTemplate>
 8: <TextBlock Text="{Binding NodeText}" TextWrapping="Wrap" Width="400"/>
 9: </DataTemplate>
 10: </core:HierarchicalDataTemplate.HeaderTemplate>
 11: </core:HierarchicalDataTemplate>
 12:  
 13: </UserControl.Resources>

16. Next step is to create the TreeView and apply the item template and the data source.

 1: <telerik:RadTreeView
 2: HorizontalAlignment="Left"
 3: VerticalAlignment="Top"
 4: ItemsSource="{Binding Source={StaticResource Source}}"
 5: ItemTemplate="{StaticResource NodeTemplate}" 
 6: />

 

17. If you decide to build, Visual Studio will encounter an error at the line

 3: <local:HierarchicalDataSource x:Key="Source" />

 

18. In the RadTreeViewWithWCF project add a new class called HierarchicalDataSource.cs. Make this class inherit from ObservableCollection<TableItem>.

 1: public class HierarchicalDataSource : ObservableCollection<TableItem>

Try to build and you will get an error telling you that you are missing the TableItem class. Therefore we need to create the TableItem class. This class is going to represent a single entry from the FoxTVSeries table. This means that this class is going to have properties like NodeID, ParentID, NodeText and one additional property called Children. The Children property will be used to turn the flat data into hierarchical one.

 1: public class TableItem
 2: {
 3: private string nodeText;
 4: private int nodeID;
 5: private System.Nullable<int> parentID;
 6: private List<TableItem> children;
 7:  
 8: public TableItem(string nodeText, int nodeID, System.Nullable<int> parentID)
 9:     {
 10: this.nodeText = nodeText;
 11: this.nodeID = nodeID;
 12: this.parentID = parentID;
 13:  
 14: this.children = new List<TableItem>();
 15:     }
 16:  
 17: public string NodeText
 18:     {
 19:         get
 20:         {
 21: return this.nodeText;
 22:         }
 23:     }
 24: public System.Nullable<int> ParentID
 25:     {
 26:         get
 27:         {
 28: return this.parentID;
 29:         }
 30:     }
 31: public int NodeID
 32:     {
 33:         get
 34:         {
 35: return this.nodeID;
 36:         }
 37:     }
 38: public List<TableItem> Children
 39:     {
 40:         get
 41:         {
 42: return this.children;
 43:         }
 44:     }
 45: }

Once the TableItem class is done, we are ready to proceed with the HierarchicalDataSource class.

 1: public class HierarchicalDataSource : ObservableCollection<TableItem>
 2: {
 3: // This list holds all the items that come from the web service result
 4: private List<TableItem> unsortedList = new List<TableItem>();
 5:  
 6: public HierarchicalDataSource()
 7:     {
 8: // Create a new instance of the web service and get the data from the table
 9:         Service1Client webService = new Service1Client();
 10:         webService.GetTVSerieCompleted += new EventHandler<GetTVSerieCompletedEventArgs>(WebService_GetTableCompleted);
 11:         webService.GetTVSerieAsync();
 12:     }
 13:  
 14: private void WebService_GetTableCompleted(object sender, GetTVSerieCompletedEventArgs e)
 15:     {
 16: // transfer all the items from the result to the unsorted list
 17: foreach (FoxTVSery item in e.Result)
 18:         {
 19:             TableItem genericItem = new TableItem(item.NodeText, item.NodeID, item.ParentID);
 20: this.unsortedList.Add(genericItem);
 21:         }
 22:  
 23: // Get all the first level nodes. In our case it is only one - House M.D.
 24:         var rootNodes = this.unsortedList.Where(x => x.ParentID == x.NodeID);
 25:  
 26: // Foreach root node, get all its children and add the node to the HierarchicalDataSource.
 27: // see bellow how the FindChildren method works
 28: foreach (TableItem node in rootNodes)
 29:         {
 30: this.FindChildren(node);
 31: this.Add(node);
 32:         }
 33:     }
 34: 
 35: private void FindChildren(TableItem item)
 36:     {
 37: // find all the children of the item
 38:         var children = unsortedList.Where(x => x.ParentID == item.NodeID && x.NodeID != item.NodeID);
 39:  
 40: // add the child to the item's children collection and call the FindChildren recursively, in case the child has children
 41: foreach (TableItem child in children)
 42:         {
 43:             item.Children.Add(child);
 44:             FindChildren(child);
 45:         }
 46:     }
 47: }

It is a pretty straightforward class. It has a list that will contain the flat data coming from the web service result. Then this list is traversed and the hierarchical data is built.

If you need any more explanations or you have any suggestions, do not hesitate to drop me a comment.

Resources:

RadTreeViewWithWCF.zip

Telerik.Windows.Controls.dll

Telerik.Windows.Controls.Navigation.dll

FoxTVSeries.mdf


About the Author

Rossen Hristov

 is Senior Software Developer in Telerik XAML Team

Related Posts

Comments