Command Support
The purpose of this article is to introduce you the command support of the RadTreeViewItems.
Overview
The RadTreeViewItem exposes a Command property of type ICommand. You can use this property to trigger custom logic defined in your business object. Furthermore, you can set the CommandExecutionTrigger property. This property is an enumeration which controls whether the command should be executed after a Click or a DoubleClick on the corresponding RadTreeViewItem.
Demonstration
In this section we will demonstrate how you can trigger custom logic implemented in your business object using the Command Support of the RadTreeViewItem. Hence we will need to create a custom class implementing the INotifyPropertyChanged interface and exposing the following properties:
- Header of type string
-
Children of type ObservableCollection
- EditCommand of type DelegateCommand
- IsInEditMode of type bool
The ViewModelBase class implements the INotifyPropertyChanged interface.
public class ItemModel : ViewModelBase
{
private bool inInEditMode;
public bool IsInEditMode
{
get
{
return this.inInEditMode;
}
set
{
if (this.inInEditMode != value)
{
this.inInEditMode = value;
this.OnPropertyChanged("IsInEditMode");
}
}
}
private string header;
public string Header
{
get
{
return this.header;
}
set
{
if (this.header != value)
{
this.header = value;
this.OnPropertyChanged("Header");
}
}
}
public DelegateCommand EditCommand { get; set; }
public ObservableCollection<ItemModel> Children { get; set; }
}
Public Class ItemModel
Inherits ViewModelBase
Private inInEditMode As Boolean
Public Property IsInEditMode() As Boolean
Get
Return Me.inInEditMode
End Get
Set(value As Boolean)
If Me.inInEditMode <> value Then
Me.inInEditMode = value
Me.OnPropertyChanged("IsInEditMode")
End If
End Set
End Property
Private m_header As String
Public Property Header() As String
Get
Return Me.m_header
End Get
Set(value As String)
If Me.m_header <> value Then
Me.m_header = value
Me.OnPropertyChanged("Header")
End If
End Set
End Property
Public Property EditCommand() As DelegateCommand
Get
Return m_EditCommand
End Get
Set(value As DelegateCommand)
m_EditCommand = Value
End Set
End Property
Private m_EditCommand As DelegateCommand
Public Property Children() As ObservableCollection(Of ItemModel)
Get
Return m_Children
End Get
Set(value As ObservableCollection(Of ItemModel))
m_Children = Value
End Set
End Property
Private m_Children As ObservableCollection(Of ItemModel)
End Class
Furthermore, we can create a ViewModel class which will fill and expose an Items collection of type ObservableCollection
public class ViewModel
{
public ViewModel()
{
this.Items = new ObservableCollection<ItemModel>();
this.GenerateItems();
}
public ObservableCollection<ItemModel> Items { get; set; }
private void GenerateItems()
{
ObservableCollection<ItemModel> children;
for (byte j = 1; j < 5; j++)
{
children = new ObservableCollection<ItemModel>();
for (byte i = 1; i < 4; i++)
{
children.Add(new ItemModel()
{
Header = string.Format("Child {0} of root {1}", i, j),
EditCommand = new DelegateCommand((x) => this.OnEditCommandExecute(x))
});
}
this.Items.Add(new ItemModel()
{
Header = string.Format("Root Item {0}", j),
Children = children,
EditCommand = new DelegateCommand((x) => this.OnEditCommandExecute(x))
});
}
}
private void OnEditCommandExecute(object sender)
{
var item = sender as ItemModel;
if (item != null)
{
item.IsInEditMode = true;
}
}
}
Public Class ViewModel
Public Sub New()
Me.Items = New ObservableCollection(Of ItemModel)()
Me.GenerateItems()
End Sub
Public Property Items() As ObservableCollection(Of ItemModel)
Get
Return m_Items
End Get
Set(value As ObservableCollection(Of ItemModel))
m_Items = Value
End Set
End Property
Private m_Items As ObservableCollection(Of ItemModel)
Private Sub GenerateItems()
Dim children As ObservableCollection(Of ItemModel)
For j As Byte = 1 To 4
children = New ObservableCollection(Of ItemModel)()
For i As Byte = 1 To 3
children.Add(New ItemModel() With {
.Header = String.Format("Child {0} of root {1}", i, j),
.EditCommand = New DelegateCommand(Function(x) Me.OnEditCommandExecute(x))
})
Next
Me.Items.Add(New ItemModel() With {
.Header = String.Format("Root Item {0}", j),
.Children = children,
.EditCommand = New DelegateCommand(Function(x) Me.OnEditCommandExecute(x))
})
Next
End Sub
Private Sub OnEditCommandExecute(sender As Object)
Dim item = TryCast(sender, ItemModel)
If item IsNot Nothing Then
item.IsInEditMode = True
End If
End Sub
End Class
In MVVM scenarios it is best to use a Style to set the Command and CommandExecutionTrigger properties of the RadTreeViewItems. For this purpose we will also allow the editing of items and we will use the boolean IsInEditMode property defined in the custom ItemModel class to set the corresponding RadTreeViewItem in edit mode. This will be done in the OnEditCommandExecute() method implemented in the ViewModel class. In order to differ the item that invokes the command we can pass each RadTreeViewItem's DataContext as CommandParameter to the method where custom logic will be implemented. In order to achieve this we can use the RelativeSource binding.
<Grid>
<Grid.Resources>
<HierarchicalDataTemplate x:Key="HDT" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header, Mode=TwoWay}" />
</HierarchicalDataTemplate>
<Style TargetType="telerik:RadTreeViewItem">
<Setter Property="Command" Value="{Binding EditCommand}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandExecutionTrigger" Value="DoubleClick" />
<Setter Property="IsInEditMode" Value="{Binding IsInEditMode, Mode=TwoWay}" />
</Style>
</Grid.Resources>
<telerik:RadTreeView IsEditable="True"
IsExpandOnDblClickEnabled="False"
ItemTemplate="{StaticResource HDT}"
ItemsSource="{Binding Items}" />
</Grid>