Expand and Select Item with Load on Demand Enabled RadTreeView
This tutorial will demonstrate you how to expand and select an item when the RadTreeView is in load on demand mode (IsLoadOnDemandEnabled property is set to True).
For the purpose of this topic a RadTreeView which is data bound to a business object will be used. The next several code snippets show you the RadTreeView declaration and the business object structure.
<Grid>
<Grid.Resources>
<telerik:HierarchicalDataTemplate x:Key="treeViewTemplate" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Title}" />
</telerik:HierarchicalDataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<telerik:RadTreeView x:Name="treeView"
Margin="8"
HorizontalAlignment="Stretch"
IsLoadOnDemandEnabled="True"
IsVirtualizing="True"
ItemTemplate="{StaticResource treeViewTemplate}"
telerik:TextSearch.TextPath="Title" />
<StackPanel Grid.Column="1"
Width="300"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Button Click="Button_Click_1" Content="Bring Item" />
<TextBox x:Name="userInput" />
</StackPanel>
</Grid>
The data source for the radtreeview will be consisted of DataItems, only.
public class DataItem : ViewModelBase
{
private string title;
private List<DataItem> children;
public String Title
{
get
{
return this.title;
}
set
{
if (this.title != value)
{
this.title = value;
this.OnPropertyChanged("Title");
}
}
}
public List<DataItem> Children
{
get
{
return this.children;
}
}
}
Public Class DataItem
Inherits ViewModelBase
Private m_title As String
Private m_children As List(Of DataItem)
Public Property Title() As [String]
Get
Return Me.m_title
End Get
Set(value As [String])
If Me.m_title <> value Then
Me.m_title = value
Me.OnPropertyChanged("Title")
End If
End Set
End Property
Public ReadOnly Property Children() As List(Of DataItem)
Get
Return Me.m_children
End Get
End Property
End Class
Set a DataItem instance to the ItemsSource property of the RadTreeView and create some simple data like in the code snippet below.
this.treeView.ItemsSource = Enumerable.Range(1, 10).Select(i => new DataItem()
{
Title = string.Format("Item {0}", i)
}).ToList();
The actual loading on demand of the business items can be implemented in the getter of the Children property of the DataItem class. The LoadOnDemand feature of the RadTreeView control is used to visualize the expander icon in the front of each RadTreeViewItem. We do not use the built-in LoadOnDemand event to load the business items into the control. Instead, the HierarchicalDataTemplate will trigger the getter of its ItemsSource property on load. For demonstration purposes, we will load a fixed number of business data every time the getter is triggered and the children field is not yet instantiated.
public List<DataItem> Children
{
get
{
if (this.children == null)
{
this.children = new List<DataItem>();
for (int i = 0; i < 5; i++)
{
DataItem item = new DataItem() { Title = string.Format("{0}.{1}", this.Title, i) };
this.children.Add(item);
}
}
return this.children;
}
}
Public ReadOnly Property Children() As List(Of DataItem)
Get
If Me.children Is Nothing Then
Me.children = New List(Of DataItem)()
For i As Integer = 0 To 4
Dim item As New DataItem() With { _
Key .Title = String.Format("{0}.{1}", Me.Title, i) _
}
Me.children.Add(item)
Next
End If
Return Me.children
End Get
End Property
The next step is to implement the custom logic for creating the path in order to use the BringPathIntoView() method.
private void Button_Click_1(object sender, RoutedEventArgs e)
{
string[] headerAndIndexes = this.userInput.Text.Split(' ');
string[] indexes = headerAndIndexes.LastOrDefault().Split('.');
bool areIndexesValid = false;
int i;
if (headerAndIndexes != null && indexes != null)
{
foreach (string index in indexes)
{
areIndexesValid = int.TryParse(index, out i);
}
if (headerAndIndexes.FirstOrDefault().Contains("Item") && areIndexesValid)
{
RadTreeViewItem item = this.treeView.GetItemByPath(this.GenetatePath(this.userInput.Text));
if (item != null)
{
item.IsSelected = true;
item.IsExpanded = true;
}
}
}
}
private string GenetatePath(string itemToExpand)
{
string path = string.Empty;
string buffer;
string[] header = itemToExpand.Split(' ');
string[] indexes = header.LastOrDefault().Split('.');
header[0] = string.Format("{0} {1}", header[0], indexes[0]);
path = string.Format("{0}\", header[0]);
for (int i = 1; i < indexes.Length; i++)
{
buffer = string.Format("{0}.{1}", header[0], indexes[i]);
header[0] = buffer;
path += string.Format("{0}\", buffer);
}
return path.TrimEnd('\');
}
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
Dim headerAndIndexes As String() = Me.userInput.Text.Split(" "c)
Dim indexes As String() = headerAndIndexes.LastOrDefault().Split("."c)
Dim areIndexesValid As Boolean = False
Dim i As Integer
If headerAndIndexes IsNot Nothing AndAlso indexes IsNot Nothing Then
For Each index As String In indexes
areIndexesValid = Integer.TryParse(index, i)
Next
If headerAndIndexes.FirstOrDefault().Contains("Item") AndAlso areIndexesValid Then
Dim item As RadTreeViewItem = Me.treeView.GetItemByPath(Me.GenetatePath(Me.userInput.Text))
If item IsNot Nothing Then
item.IsSelected = True
item.IsExpanded = True
End If
End If
End If
End Sub
Private Function GenetatePath(itemToExpand As String) As String
Dim path As String = String.Empty
Dim buffer As String
Dim header As String() = itemToExpand.Split(" "c)
Dim indexes As String() = header.LastOrDefault().Split("."c)
header(0) = String.Format("{0} {1}", header(0), indexes(0))
path = String.Format("{0}\", header(0))
For i As Integer = 1 To indexes.Length - 1
buffer = String.Format("{0}.{1}", header(0), indexes(i))
header(0) = buffer
path += String.Format("{0}\", buffer)
Next
Return path.TrimEnd("\"c)
End Function
The final result after bringing Item 2.3.1.4 should look like this