.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"