Yes - this is a major and very important concept of the Silverlight/WPF ItemsControl. It is not related to the implementation of the RadTreeView, but you will see it in any control that derives from ItemsControl (another example is the ListBox).
The Items collection of the ItemsControl is a collection of
data objects , NOT from RadTreeViewItems. There is a very important concept in Silverlight/WPF about the items and item containers. When you bind an ItemsControl you have your data items populating the
Items collection of the control. The containers are the
visual presentations of those data items (in our case the containers are the RadTreeViewItems). Containers are not created automatically when the ItemsControl is bound, but are created
asyncronously and only when needed. For example in our case with the TreeView, the containers are not being created until there parent is expanded.
So how you can get the container from the data item? Or in our case - how to get the RadTreeViewItem from your data object that you receive when traversing the Items collection?
There are several helper methods that can be used. Each ItemsControl have a Property named
ItemContainerGenerator. It is of type
ItemContainerGenerator . This class has the following methods that can helps us in our case:
-
DependencyObject ContainerFromIndex(int index) - returns the Container for the given index from the Items collection.
-
DependencyObject ContainerFromItem(object item) - returns the Container for the given data item from the Items collection.
So here is an example about how to get access to all the Containers in the RadTreeView:
void getContainers() |
{ |
|
// gets all nodes from the TreeView |
Collection<RadTreeViewItem> allTreeContainers = GetAllItemContainers(tree1); |
|
// gets all nodes (recursively) for the first node |
RadTreeViewItem firstNode = tree1.ItemContainerGenerator.ContainerFromIndex(0) as RadTreeViewItem; |
if (firstNode != null) |
{ |
Collection<RadTreeViewItem> firstNodeContainers = GetAllItemContainers(firstNode); |
} |
|
|
} |
|
Collection<RadTreeViewItem> GetAllItemContainers(Telerik.Windows.Controls.ItemsControl itemsControl) |
{ |
|
Collection<RadTreeViewItem> allItems = new Collection<RadTreeViewItem>(); |
|
for (int i = 0; i < itemsControl.Items.Count; i++) |
{ |
// try to get the item Container |
RadTreeViewItem childItemContainer = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as RadTreeViewItem; |
|
// the item container maybe null if it is still not generated from the runtime |
if (childItemContainer != null) |
{ |
allItems.Add(childItemContainer); |
|
Collection<RadTreeViewItem> childItems = GetAllItemContainers(childItemContainer); |
foreach (RadTreeViewItem childItem in childItems) |
{ |
allItems.Add(childItem); |
} |
} |
} |
return allItems; |
} |
|
I hope this makes the picture a little more clear. These concepts are all borowed from WPF and it is hard to understand without to play with the ItemsControl for some time. I can recommend the following great blogs posts which are written for WPF, but they explain the concept very well and will be of help for the Silverlight learning:
http://blog.quantumbitdesigns.com/2008/05/22/programmatically-selecting-an-item-in-a-treeview/
http://www.drwpf.com/blog/Home/tabid/36/EntryID/32/Default.aspx - all posts regarding the ItemsControl.
Please let us know if you still have any questions regarding those concepts!
All the best,
Valentin.Stoychev
the Telerik team