Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon

How to implement data validation with Xamarin.Forms

Save for later
  • 8 min read
  • 03 Feb 2020

article-image

In software, data validation is a process that ensures the validity and integrity of user input and usually involves checking that that data is in the correct format and contains an acceptable value. In this Xamarin tutorial, you'll learn how to implement it with Xamarin.Forms.

This article is an excerpt from the book Mastering Xamarin.Forms, Third Edition by Ed Snider. The book walks you through the creation of a simple app, explaining at every step why you're doing the things you're doing, so that you gain the skills you need to use Xamarin.Forms to create your own high-quality apps.

Types of data validation in mobile application development


There are typically two types of validation when building apps: server-side and client-side. Both play an important role in the lifecycle of an app's data. Server-side validation is critical when it comes to security, making sure malicious data or code doesn't make its way into the server or backend infrastructure. Client-side validation is usually more about user experience than security. A mobile app should always validate its data before sending it to a backend (such as a web API) for several reasons, including the following:

  • To provide real time feedback to the user about any issues instead of waiting on a response from the backend.
  • To support saving data in offline scenarios where the backend is not available.
  • To prevent encoding issues when sending the data to the backend.


Just as a backend server should never assume all incoming data has been validated by the client-side before being received, a mobile app should also never assume the backend will do its own server-side validation, even though it's a good security practice. For this reason, mobile apps should perform as much client-side validation as possible.

When adding validation to a mobile app the actual validation logic can go in a few areas of the app architecture. It could go directly in the UI code (the View layer of an Model-View-ViewModel (MVVM) architecture), it could go in the business logic or controller code (the ViewModel layer of an MVVM architecture), or it could even go in the HTTP code. In most cases when implementing the MVVM pattern it will make the most sense to include validation in the ViewModels for the following reasons:

  • The validation rules can be checked as the individual properties of the ViewModel are changed.
  • The validation rules are often part of or dependent on some business logic that exists in the ViewModel.
  • Most importantly, having the validation rules implemented in the ViewModel makes them easy to test.

Adding a base validation ViewModel in Xamarin.Forms


Validation makes the most sense in the ViewModel. To do this we will start by creating a new base ViewModel that will provide some base level methods, properties, and events for subclassed ViewModels to leverage. This new base ViewModel will be called BaseValidationViewModel and will subclass the BaseViewModel. It will also implement an interface called from the System.ComponentModel namespace. INotifyDataErrorInfo works a lot like INotifyPropertyChanged – it specifies some properties about what errors have occurred and as well as an event for when the error state of particular property changes.

  1. Create a new class in the ViewModels folder name BaseValidationViewModel that subclasses BaseViewModel:

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
Create a new class in the ViewModels folder name BaseValidationViewModel that subclasses BaseViewModel: 
public class BaseValidationViewModel : BaseViewModel 
{ 
    public BaseValidationViewModel(INavService navService) 
        : base(navService) 
    { 
    } 
}


2. Update BaseValidationViewModel to implement INotifyDataErrorInfo as follows:

public class BaseValidationViewModel : BaseViewModel, 
    INotifyDataErrorInfo 
{ 
    readonly IDictionary<string, List<string>> _errors =  
        new Dictionary<string, List<string>>(); 

    public BaseValidationViewModel(INavService navService) 
        : base(navService) 
    { 
    } 
 
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; 

    public bool HasErrors =>  
        _errors?.Any(x => x.Value?.Any() == true) == true; 
    public IEnumerable GetErrors(string propertyName) 
    { 
        if (string.IsNullOrWhiteSpace(propertyName)) 
        { 
            return _errors.SelectMany(x => x.Value); 
        } 
 
        if (_errors.ContainsKey(propertyName)  
            && _errors[propertyName].Any()) 
        { 
            return _errors[propertyName]; 
        } 
 
        return new List<string>(); 
    } 
}


3. In addition to implementing the required members of INotifyDataErrorInfo – ErrorChanged, HasErrors, and GetErrors() – we also need to add a method that actually handles validating ViewModel properties. This method needs a validation rule parameter in the form of a Func<bool> and an error message to be used if the validation rule fails. Add a protected method named Validate to BaseValidationViewModel as follows:

public class BaseValidationViewModel : BaseViewModel,  
    INotifyDataErrorInfo 
{ 
    // ... 
 
    protected void Validate(Func<bool> rule, string error, 
        [CallerMemberName] string propertyName = "") 
    { 
        if (string.IsNullOrWhiteSpace(propertyName)) return; 
 
        if (_errors.ContainsKey(propertyName)) 
        { 
            _errors.Remove(propertyName); 
        } 
 
        if (rule() == false) 
        { 
            _errors.Add(propertyName, new List<string> { error }); 
        } 
 
        OnPropertyChanged(nameof(HasErrors)); 
 
        ErrorsChanged?.Invoke(this,  
            new DataErrorsChangedEventArgs(propertyName)); 
    } 
}


If the validation rule Func<bool> returns false, the error message that is provided is added to a private list of errors-used by HasErrors and GetErrors()-mapped to the specific property that called into this Validate() method. Lastly, the Validate() method invokes the ErrorsChanged event with the caller property's name included in the event arguments.

Now any ViewModel that needs to perform validation can subclass BaseValidationViewModel and call the Validate() method to check if individual properties are valid.

In the next section, we will use BaseValidationViewModel to add validation to the new entry page and its supporting ViewModel.

Adding validation to the new entry page in Xamarin.Forms


In this section we will add some simple client-side validation to a couple of the entry fields on the new entry page.

  1. First, update NewEntryViewModel to subclass BaseValidationViewModel instead of BaseViewModel.

public class NewEntryViewModel : BaseValidationViewModel 
{ 
    // ... 
}


Because BaseValidationViewModel subclasses BaseViewModel, NewEntryViewModel is still able to leverage everything in BaseViewModel as well.

2. Next, add a call to Validate() in the Title property setter that includes a validation rule specifying that the field cannot be left blank:

public string Title 
{ 
    get => _title; 
    set 
    { 
        _title = value; 
        Validate(() => !string.IsNullOrWhiteSpace(_title),  
            "Title must be provided."); 
        OnPropertyChanged(); 
        SaveCommand.ChangeCanExecute(); 
}


3. Next, add a call to Validate() in the Rating property setter that includes a validation rule specifying that the field's value must be between 1 and 5:

public int Rating 
{ 
    get => _rating; 
    set 
    { 
        _rating = value; 
        Validate(() => _rating >= 1 && _rating <= 5, 
            "Rating must be between 1 and 5."); 
        OnPropertyChanged(); 
        SaveCommand.ChangeCanExecute(); 
}


Notice we also added SaveCommand.ChangeCanExecute() to the setter as well. This is because we want to update the SaveCommand's canExecute value when this value as changed since it will now impact the return value of CanSave(), which we will update in the next step.

4. Next, update CanSave() – the method used for the SaveCommand's canExecute function – to prevent saving if the ViewModel has any errors:

bool CanSave() => !string.IsNullOrWhitespace(Title) && !HasErrors;


5. Finally, update the new entry page to reflect any errors by highlighting the field's text color in red:

// NewEntryPage.xaml: 
 
<EntryCell x:Name="title" Label="Title" Text="{Binding Title}" /> 
// ... 
<EntryCell x:Name="rating" Label="Rating" Keyboard="Numeric" 
           Text="{Binding Rating}" /> 
 
// NewEntryPage.xaml.cs: 
 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using Xamarin.Forms; 
using TripLog.ViewModels;  
 
public partial class NewEntryPage : ContentPage 
{ 
    NewEntryViewModel ViewModel =>  
        BindingContext as NewEntryViewModel; 
 
    public NewEntryPage() 
    { 
        InitializeComponent(); 
 
        BindingContextChanged += Page_BindingContextChanged; 
 
        BindingContext = new NewEntryViewModel(); 
    } 
 
    void Page_BindingContextChanged(object sender, EventArgs e) 
    { 
        ViewModel.ErrorsChanged += ViewModel_ErrorsChanged; 
    } 
 
    void ViewModel_ErrorsChanged(object sender, 
        DataErrorsChangedEventArgs e) 
    { 
        var propHasErrors = (ViewModel.GetErrors(e.PropertyName) 
            as List<string>)?.Any() == true; 
 
        switch (e.PropertyName) 
        { 
            case nameof(ViewModel.Title): 
                title.LabelColor = propHasErrors  
                    ? Color.Red : Color.Black; 
                break; 
            case nameof(ViewModel.Rating): 
                rating.LabelColor = propHasErrors 
                    ? Color.Red : Color.Black; 
                break; 
            Default: 
                break; 
        } 
    } 
}


Now when we run the app we will see the following screenshots:

[caption id="attachment_31034" align="aligncenter" width="846"]how-to-implement-data-validation-with-xamarin-forms-img-0 The TripLog new entry page with client-side validation[/caption]

Navigate to the new entry page and enter an invalid value in either the Title or Rating field we will see the field label turn red and the Save button will be disabled. Once the error has been corrected the field label color returns to black and the Save button is re-enabled.

Learn more mobile application development with Xamarin and the open source Xamarin.Forms toolkit with the third edition Mastering Xamarin.Forms.

About Ed Snider


Ed Snider is a senior software developer, speaker, author, and Microsoft MVP based in the Washington D.C./Northern Virginia area. He has a passion for mobile design and development and regularly speaks about Xamarin and Windows app development in the community. Ed works at InfernoRed Technology, where his primary role is working with clients and partners to build mobile and media focused products on iOS, Android, and Windows. He started working with.NET in 2005 when .NET 2.0 came out and has been building mobile apps with .NET since 2011. Ed was recognized as a Xamarin MVP in 2015 and as a Microsoft MVP in 2017.

Find him on Twitter: @edsnider