How to bind DataGrid built-in commands in the ViewModel
Environment
Product Version | R1 2021 |
Product | DataGrid for Xamarin |
Description
RadDataGrid exposes a few predefined commands, such as CellTap, ColumnHeaderTap, BeginEdit etc, associated with various user-actions over the grid. You can easily handle any of these commands by creating a custom command class that derives from DataGridCommand
class, set its CommandId and implement Execute and CanExecute methods. For detailed information on this, check Commands Overview topic.
This topic demonstrates a sample approach for handling the DataGrid commands inside the ViewModel through an additional class used for the command binding. For the purpose of the example, we'll use CommitEdit command which is raised as soon as a cell value has been modified by the user.
Solution
Let's start with creating the CustomDataGridCommand which derives from DataGridCommand
:
public class CustomDataGridCommand : DataGridCommand
{
public static readonly BindableProperty CommandProperty = BindableProperty.Create(
nameof(Command), typeof(ICommand), typeof(CustomDataGridCommand), null);
public ICommand Command
{
get { return (ICommand)this.GetValue(CommandProperty); }
set { this.SetValue(CommandProperty, value); }
}
public override bool CanExecute(object parameter)
{
bool canExecuteDefaultCommand = this.Owner?.CommandService?.CanExecuteDefaultCommand(this.Id, parameter) ?? false;
bool canExecuteCommand = this.Command?.CanExecute(parameter) ?? true;
return canExecuteDefaultCommand && canExecuteCommand;
}
public override void Execute(object parameter)
{
this.Owner?.CommandService?.ExecuteDefaultCommand(this.Id, parameter);
this.Command?.Execute(parameter);
}
}
Then, create a sample ViewModel class - add a CommitEditCommand property of type ICommand
:
public class ViewModel : NotifyPropertyChangedBase
{
private ICommand _commitEditCommand;
public ViewModel()
{
this.Source = new ObservableCollection<Data>()
{
new Data { Country = "India", Capital = "New Delhi"},
new Data { Country = "South Africa", Capital = "Cape Town"},
new Data { Country = "Nigeria", Capital = "Abuja" },
new Data { Country = "Singapore", Capital = "Singapore" }
};
this.CommitEditCommand = new Command(this.CommitEditExecute);
}
public ObservableCollection<Data> Source { get; set; }
public ICommand CommitEditCommand
{
get { return this._commitEditCommand; }
set
{
if (this._commitEditCommand != value)
{
this._commitEditCommand = value;
this.OnPropertyChanged();
}
}
}
private void CommitEditExecute(object param)
{
var context = (EditContext)param;
}
}
The used Data
class:
public class Data
{
public string Country { get; set; }
public string Capital { get; set; }
}
Lastly, add the RadDataGrid instance with the CustomDataGridCommand attached to its Commands collection:
<telerikDataGrid:RadDataGrid x:Name="dataGrid"
ItemsSource="{Binding Source}"
UserEditMode="Cell">
<telerikDataGrid:RadDataGrid.Commands>
<local:CustomDataGridCommand Id="CommitEdit" Command="{Binding CommitEditCommand}" />
</telerikDataGrid:RadDataGrid.Commands>
</telerikDataGrid:RadDataGrid>
The final step is to set the ViewModel class as a BindingContext:
this.BindingContext = new ViewModel();
As soon as the user edits a value, there will be notification in the ViewModel CommitEditExecute method with information on the updated bits (through the EditContext parameter).