Validate input in Xamarin.Forms using INotifyDataErrorInfo, custom Behaviors, Effects and Prism

This post is also available in the Premier Developer blog.

I have recently been investigating the support available in Xamarin.Forms for validation and, in particular, researched the possibility of using INotifyDataErrorInfo to complement the traditional approach of using Behaviors.

In simple scenarios, it’s possible to perform validation by simply attaching a Behavior to the required view, as shown by the following sample code:

In this case, we are validating the input and modifying the UI if the number of characters entered is less than 5.

What about more articulated scenarios when multiple business rules are required to be checked for the input values?

In these cases, we could take advantage of other types available to make our code more structured and extensible:

  • INotifyDataErrorInfo: available in Xamarin.Forms. When implemented it permits specifying custom validation supporting multiple errors per property, cross-property errors and entity-level errors;
  • DataAnnotations decorate the data models using attributes which specify validation conditions to be applied to the specific field;
  • Forms Behaviors specify the specific UI to be applied to the specific validation scenarios, integrating with INotifyDataErrorInfo and DataAnnotations.

To start exploring this approach, I created a new Xamarin.Forms Prism solution using the Prism Template Pack which generated the following project structure:

Then, I added the following new model to be validated using DataAnnotations and INotifyDataErrorInfo:

The model uses attributes declared in the SystemComponentModel.DataAnnotations namespace which can be referenced in the solution modifying the Portable Class Library profile of the UsingValidation common project:

Quick tip: to be able to change the PCL profile I had to remove all the NuGet packages used by the common project, remove the Windows Phone 8 profile and then add back all the removed NuGet packages to the UsingValidation PCL.

To use the capability offered by INotifyDataErrorInfo, the model needs to implements 3 members defined in the interface:

  • GetErrors() returns an IEnumerable sequence of strings containing the error messages triggered by validation;
  • the HasErrors property returns a boolean value indicating if there are validation errors;
  • ErrorsChanged event can be triggered to Notify if the validation errors have been updated.

This interface is quite flexible and is designed to be customised depending on the different scenarios needed: I took as a starting point this implementation available on GitHub and modified it accordingly: I decided to separate the implementation of INotifyDataErrorInfo in a different base class called ValidationBase which contains the following code using a Dictionary<string, List<string>> needed for storing the generated validation errors:

The validation is performed by this method which evaluates the DataAnnotations decorating the model using the Validator available in the System.ComponentModel.DataAnnotations namespace and then stores the error messages in the dictionary:

At this stage, I needed a solution for linking the UI to the model, and modifying the visuals depending on the presence or not of validation errors.

The ViewModel for the sample page, contains only a property storing an instance of the item defined in the model:

Then, the corresponding XAML contains two Entry views used for input and a ListView used for showing the validation errors:

The sample page uses a Behavior called EntryValidationBehavior which take care of changing the colour of the Entry background views in the case validation errors are present:

The UI is also fine-tuned using a Xamarin.Forms effect applied only to the UWP platform, in order to change the colour of the Entry border when validation errors occur:

And this is the result when the application is executed on Android and UWP:

Conclusions

Xamarin.Forms provides a rich set of features for implementing validation: the usage of INotifyDataErrorInfo, Data Annotations, Behaviors and Effects permit the handling of complex scenarios including multiple conditions per field, cross-property validation, entity-level validation and custom UI depending on the platform.

The source code of the sample demo is available for download on GitHub here.

Happy coding!