I had an idea recently to start a new side project that would help me learn Silverlight as well as provide a valuable service to RCM, the company that I am currently employed with. My goal was to use to provide a clean interface to allow managers to get at certain bits of information needed to make decisions.
One of the requirements was the ability to display employees by office, thus I decided I would see how the scenario of binding Hierarchial data would be done using XAML; also I wanted to start building my experience with MVVm.
Note: As of SilverLight 4 the TreeView is now a standard component
Here is the basic XAML for the Treeview on my XAML page:
Side Note: Great resource for understanding many of the components in SilverLight 4:
Silverlight Toolkit Samples
Notice that we can easily create a static structure using TreeViewItem tags:
Of course, honestly, this isnt very useful and you can figure this much out about the control just by looking. Lets talk about data binding, which is one of the forte’s for XAML.
The first thing to understand is that you will not be using the typical ItemTemplate for this because it does not handle hierarchial data, instead we use the HierarchicalDataTemplate:
Now, my first thought was the HierarchialDataTemplate would take, as its ItemsSource, something which inherits IDictionary, not true, it actually requires a ObservableCollection. Before we get to addressing that lets flush out the data we are going to use for this exercise: a collection of sports teams from various leagues.
Finally, I developed the following method to do the grouping in anticipation that this would be the construct that would be used to display the data:
However, as I mentioned before this needed to be converted into a listing that could be used, but I couldnt just use GetAllTeams, it had to have a particular structure. A common property, for example, to act as the display. Thus I created the HierarchyGrouping class to act as a proxy for groupings. The structure is general enough:
This is the necessary structure for the HierarchialDataTemplate to operate properly. Because of this conversion the MVVm pattern makes excellent sense as a means to facilitate the conversion, here is the TestPageViewModel class:
What we are doing here is defining a common property with a private setter so that the ViewModel class sets it. Ideally, we would like this to be an ObservableCollection, but in this case we are not going to be changing this list.
With our list set, it is time to update our XAML to bind the source:
I have added three things to this code that are of note:
- ItemsSource on sdk:TreeView – this indicates the property off the ViewModel that will server as the source of items for the control as a whole. Note that this corresponds to our GroupListing property that we defined on the TestPageViewModel – this is not a coincidence.
- ItemsSource on the HierarchicalDataTemplate – This is where things start to get a bit curious, notice that I am specifying the property on the HierarchyGrouping which contains the sub-elements relating to the parent. This is actually very flexible, because the possibility of n levels is easily supported.
- TextBlock – this really confused me at first. This is how you want to display each item in the list, because every thing is considered to be of the same; hence the same type being used to hold the values. Here I am simply binding to our Display property, which is ubiquitously available.
Now, I can already guess the next question on your mind, “but I want to style the parent nodes differently then the leaf nodes!” The answer to this question is using a Nested HierarchicalDataTemplate. You can get information for that here: http://www.silverlight.net/content/samples/sl4/toolkitcontrolsamples/run/default.html
Now lets finish up, we just need to add a bit of code and witness how MVVm ensure we write less code and leverage the power of the XAML interpreter. This small bit of code will take care of all the binding to be done:
This is the essence of MVVm; as every control in XAML has a DataContext property we can leverage this fact and set the ViewModel as the DataContext of the page and all of our binding is handled by the XAML. Combine this with Observable properties and the ease of writing interactive code skyrockets. So if your application is working you should see something like this: