.NET MAUI DataGrid Validation Command
The .NET MAUI DataGrid control provides a validation command that has an entry point for validating cells content. The execution parameter is of type ValidateCellContext
and exposes the following properties:
-
CellInfo
—Gets the cell information associated with the operation. -
Errors
—Gets or sets the errors (if any) that occurred during the validation.
Example
Here is an example how the DataGrid ValidateCell
command works:
1. Create a Data
class (the business object) that inherits from the INotifyDataErrorInfo
and INotifyPropertyChanged
interfaces. For demonstration purposes, the example will do the validation through the INotifyDataErrorInfo
interface.
public class Data : INotifyDataErrorInfo, INotifyPropertyChanged
{
private Dictionary<string, HashSet<object>> errors = new Dictionary<string, HashSet<object>>();
private string country;
public string Country
{
get
{
return this.country;
}
set
{
this.country = value;
if (this.country.Length > 15)
{
this.AddError("Country", string.Format("Country too long", new DateTime()));
}
else
{
this.RemoveErrors("Country");
}
this.OnPropertyChanged("Country");
}
}
public string Capital { get; set; }
public bool HasErrors
{
get
{
return this.errors.Count > 0;
}
}
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
return this.errors.SelectMany(c => c.Value);
}
HashSet<object> propertyErrors;
this.errors.TryGetValue(propertyName, out propertyErrors);
return propertyErrors ?? Enumerable.Empty<object>();
}
protected virtual void AddError(string propertyName, object errorMessage)
{
HashSet<object> propertyErrors;
if (!this.errors.TryGetValue(propertyName, out propertyErrors))
{
propertyErrors = new HashSet<object>();
this.errors.Add(propertyName, propertyErrors);
propertyErrors.Add(errorMessage);
this.OnErrorsChanged(propertyName);
}
else
{
if (!propertyErrors.Contains(errorMessage))
{
propertyErrors.Add(errorMessage);
this.OnErrorsChanged(propertyName);
}
}
}
protected virtual void RemoveErrors(string propertyName = null)
{
if (string.IsNullOrEmpty(propertyName))
{
if (this.errors.Count > 0)
{
this.errors.Clear();
this.OnErrorsChanged(propertyName);
}
}
else
{
if (this.errors.Remove(propertyName))
{
this.OnErrorsChanged(propertyName);
}
}
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
protected virtual void OnErrorsChanged(string propertyName)
{
if (this.ErrorsChanged != null)
{
this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
2. Create a ViewModel
with a collection of Data
objects:
public class ViewModel : INotifyPropertyChanged
{
public ObservableCollection<Data> Items { get; set; }
public ViewModel()
{
this.Items = 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" }
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
3. Handle the CellTap
action as a Command
. First, create a class that inherits from the DataGridCommand
and set its Id
property. You will also need to override the CanExecute
and Execute
methods as demonstrated in the example below:
public class ValidateCellCommand : DataGridCommand
{
Grid grid;
public ValidateCellCommand(Grid grid)
{
this.Id = DataGridCommandId.ValidateCell;
this.grid = grid;
}
public override void Execute(object parameter)
{
var context = (ValidateCellContext)parameter;
this.grid.IsVisible = context.Errors.Count > 0;
}
}
4. Set the BindingContext
to be the ViewModel
and add this command to the Commands
collection of the RadDataGrid
instance:
this.BindingContext = new ViewModel();
this.dataGrid.Commands.Add(new ValidateCellCommand(errorContainer));
5. Define the DataGrid in XAML:
<Grid Margin="0,20,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="errorContainer"
IsVisible="false">
<BoxView BackgroundColor="DarkRed" />
<Label Text="country name length must be less than 15 symbols"
FontSize="15"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
TextColor="White"/>
</Grid>
<telerik:RadDataGrid x:Name="dataGrid"
Grid.Row="1"
UserEditMode="Cell"
AutoGenerateColumns="False"
ItemsSource="{Binding Items}">
<telerik:RadDataGrid.Columns>
<telerik:DataGridTextColumn PropertyName="Country" HeaderText="Country"/>
<telerik:DataGridTextColumn PropertyName="Capital" HeaderText="Capital"/>
</telerik:RadDataGrid.Columns>
</telerik:RadDataGrid>
</Grid>
6. Use the telerik
namespace:
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"