CollectionEditors
CollectionEditor and CollectionEditorPicker are editor controls that provide UI for editing collections and their items. Currently they are used in the domain of RadPropertyGrid as default editors for IEnumerable type-compatible properties, but they can be successfully used out of this context as standalone editors:
Example 1: Defining CollectionEditor
<Grid xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<telerik:CollectionEditor Source="{Binding Players}"
Header="Players" />
</Grid>
If you want CollectionEditor to work with a custom collection, then the edited collection type should implement ICollectionView and IEditableCollectionView interfaces.
Dependencies
Both of them are located in the Telerik.Windows.Controls.Data assembly (Telerik.Windows.Controls.Data.PropertyGrid namespace) and depend on the following assemblies:
Telerik.Windows.Data
Telerik.Windows.Controls
Telerik.Windows.Controls.Data
Telerik.Windows.Control.Input
Internal Structure
CollectionEditor relies on the IEditableCollectionView interface. In case that the edited collection type implements ICollectionView and IEditableCollectionView, its custom implementation is utilized and if it does not, an instance of QueryableCollectionView is used instead.
The following listed commands, defined in the CollectionEditorCommands class, invoke their IEditableCollectionView method counterparts, when they are executed:
MoveCurrentToNext
MoveCurrentToPrevious
AddNew
Delete
Customizing Commands
It is possible to customize the default commands for the CollectionEditor and the CollectionEditorPicker in a MVVM-friendly way. The following examples are using the CollectionEditor control but the same changes can be applied for the CollectionEditorPicker as well.
“Execute logic” methods
The methods listed below identify the logic that is executed when a certain command’s invocation takes place.
Example 3: CollectionEditor's executable commands
void MoveCurrentToNext();
void MoveCurrentToPrevious();
void Delete();
void AddNew();
Sub MoveCurrentToNext()
Sub MoveCurrentToPrevious()
Sub Delete()
Sub AddNew()
“Can-execute logic” methods
With the help of those methods you can identify whether a certain command can be executed or not.
Example 4: CollectionEditor's "can-execute" methods
bool CanMoveCurrentToNextExecute();
bool CanMoveCurrentToPreviousExecute();
bool CanDeleteExecute();
bool CanAddNewExecute();
Function CanMoveCurrentToNextExecute() As Boolean
Function CanMoveCurrentToPreviousExecute() As Boolean
Function CanDeleteExecute() As Boolean
Function CanAddNewExecute() As Boolean
Designing a custom CommandProvider
The first step is to create your own class that inherits from CollectionNavigatorBaseCommandProvider:
Example 5: Creating a class that provides the custom commands
public class CustomCommandProvider : CollectionNavigatorBaseCommandProvider
{
public CustomCommandProvider() : base(null)
{
}
public CustomCommandProvider(CollectionNavigatorBase collectionEditor)
: base(collectionEditor)
{
this.CollectionNavigator = collectionEditor;
}
}
Public Class CustomCommandProvider
Inherits CollectionNavigatorBaseCommandProvider
Public Sub New()
MyBase.New(Nothing)
End Sub
Public Sub New(ByVal collectionEditor As CollectionNavigatorBase)
MyBase.New(collectionEditor)
Me.CollectionNavigator = collectionEditor
End Sub
End Class
Those commands, which logic is up to get customized, should have their corresponding methods overridden. In the following example we will customize: MoveCurrentToNext, MoveCurrentToPrevious.
MoveCurrentToNext and MoveCurrentToPrevious
In case you have a requirement to ask for the customer`s approval when moving through items, you need to update the commands as in the following examples:
Example 6: Overriding the default commands
public override void MoveCurrentToNext()
{
MessageBoxResult result = MessageBox.Show("MoveCurrentToNext ?", "MoveCurrentToNext", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
this.CollectionNavigator.MoveCurrentToNext();
}
}
public override void MoveCurrentToPrevious()
{
MessageBoxResult result = MessageBox.Show("MoveCurrentToPrevious ?", "MoveCurrentToPrevious", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
this.CollectionNavigator.MoveCurrentToPrevious();
}
}
Public Overrides Sub MoveCurrentToNext()
Dim result As MessageBoxResult = MessageBox.Show("MoveCurrentToNext ?", "MoveCurrentToNext", MessageBoxButton.OKCancel)
If result = MessageBoxResult.OK Then
Me.CollectionNavigator.MoveCurrentToNext()
End If
End Sub
Public Overrides Sub MoveCurrentToPrevious()
Dim result As MessageBoxResult = MessageBox.Show("MoveCurrentToPrevious ?", "MoveCurrentToPrevious", MessageBoxButton.OKCancel)
If result = MessageBoxResult.OK Then
Me.CollectionNavigator.MoveCurrentToPrevious()
End If
End Sub
The last thing to be done is to set CommandProvider Property of the CollectionEditor to be the newly-created CustomCommandProvider class:
Example 7: Assigning the CommandProvider
<telerik:CollectionEditor x:Name="CollectionEditor"
Source="{Binding Employees}"/>
Example 8: Assigning the CommandProvider
this.CollectionEditor.CommandProvider = new CustomCommandProvider(this.CollectionEditor);
Me.CollectionEditor.CommandProvider = New CustomCommandProvider(Me.CollectionEditor)
Modifying the methods will result in the following action when trying to move to the next item:
Add/Remove Items
CollectionEditor allows you to add and remove items to the underlying collection through the Add and Remove buttons. The availability of this functionality relies on the type of the bound collection and whether it supports such operations. Figure 1 and Figure 2 show the state of the buttons when the CollectionEditor is bound to an ObservableCollection and an Array respectively.
The business object should expose a default constructor in order to have the "Add" button enabled.