Xamarin Community Toolkit is an official library provided by Xamarin which includes animations, behaviors, converters, effects, and many other things that help speed up development. Its first stable version was released in January 2021 and since then it has been widely used in cross-platform mobile development.
As an example of its power and usefulness, I’m going to show how to use the AsyncCommand and the UserStoppedTypingBehavior in your mobile forms, displaying error messages if the fields in the form are invalid.
Example
For our example, let’s start with the simple mobile form below:
1. Let’s start by adding Xamarin.CommunityToolkit in our project as a NuGet package.
2. Let’s assume the following rules for our fields and button:
- Name: must not null.
- Email: must match the pattern Regex patter
@"^\w+([-+.']\w+)@\w+([-.]\w+).\w+([-.]\w+)*$"
. Source: emailregex.com – .NET general pattern match. - Password: must contain at least 8 characters.
- Enabled the Sign up button if the fields are valid.
3. Finally, let’s define our ViewModel properties for Name, Email and Password.
Next, we bind our ViewModel properties in the XAML view:
<!--Name-->
<Label Text="Name" FontSize="15"/>
<Entry Text="{Binding Name}" Placeholder="Enter Name" HorizontalOptions="FillAndExpand" Keyboard="Text"/>
<Label Text="{Binding NameErrorMessage}" FontSize="13" IsVisible="{Binding ShowNameErrorMessage}" TextColor="Red"/>
<!--Email-->
<Label Text="Email" FontSize="15"/>
<Entry Text="{Binding Email}" Placeholder="Enter Email" HorizontalOptions="FillAndExpand" Keyboard="Email"/>
<Label Text="{Binding EmailErrorMessage}" FontSize="13" IsVisible="{Binding ShowEmailErrorMessage}" TextColor="Red"/>
<!--Password-->
<Label Text="Password" FontSize="15"/>
<Entry Text="{Binding Password}" Placeholder="Enter Password" HorizontalOptions="FillAndExpand" Keyboard="Default" IsPassword="True"/>
<Label Text="{Binding PasswordErrorMessage}" FontSize="13" IsVisible="{Binding ShowPasswordErrorMessage}" TextColor="Red"/>
4. Add AsyncCommand to the Sign up button
The AsyncCommand allows us to execute commands as an asynchronous Task, its second parameter verifies whether or not AsyncCommand should execute.
bool EnableButton => IsValidName && IsValidEmail && IsValidPassword;
SignUpCommand = new AsyncCommand(HandleSignUp, () => EnableButton);
async Task HandleSignUp()
{
await Application.Current.MainPage.DisplayAlert("Sign up completed", "Your user has been created successfully", "Ok");
}
// Name
private bool isValidName;
public bool IsValidName
{
get => isValidName;
set
{
if (SetProperty(ref isValidName, value))
{
SignUpCommand.RaiseCanExecuteChanged();
}
}
}
// Email
private bool isValidEmail;
public bool IsValidEmail
{
get => isValidEmail;
set
{
if (SetProperty(ref isValidEmail, value))
{
SignUpCommand.RaiseCanExecuteChanged();
}
}
}
// Password
private bool isValidPassword;
public bool IsValidPassword
{
get => isValidPassword;
set
{
if (SetProperty(ref isValidPassword, value))
{
SignUpCommand.RaiseCanExecuteChanged();
}
}
}
XAML
<Button HorizontalOptions="Center" Text="Sign up" Margin="0,10,0,0" BackgroundColor="LightGray" WidthRequest="100" TextColor="Black" CornerRadius="5" TextTransform="None" Command="{Binding SignUpCommand}"/>
5. Validate the fields using UserStoppedTypingBehavior with AsyncCommand
The UserStoppedTypingBehavior is a behavior integrated in Xamarin Community Toolkit that allows to execute code after the user stops typing. Let’s start by defining our rules in our ViewModel:
// Name
ValidateNameCommand = new AsyncCommand(HandleNameValidation);
Task HandleNameValidation()
{
if (!string.IsNullOrEmpty(Name))
{
IsValidName = true;
ShowNameErrorMessage = false;
}
else
{
NameErrorMessage = "*Please enter a name";
IsValidName = false;
ShowNameErrorMessage = true;
}
return Task.CompletedTask;
}
// Email
ValidateEmailCommand = new AsyncCommand(HandleEmailValidation);
string emailPattern = @"^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";
Task HandleEmailValidation()
{
if (!string.IsNullOrEmpty(Email) && Regex.IsMatch(Email, emailPattern))
{
IsValidEmail = true;
ShowEmailErrorMessage = false;
}
else
{
EmailErrorMessage = "*Invalid email";
IsValidEmail = false;
ShowEmailErrorMessage = true;
}
return Task.CompletedTask;
}
// Password
ValidatePasswordCommand = new AsyncCommand(HandlePasswordValidation);
Task HandlePasswordValidation()
{
if (!string.IsNullOrEmpty(Password) && Password.Length >= 8)
{
IsValidPassword = true;
ShowPasswordErrorMessage = false;
}
else
{
PasswordErrorMessage = "*Invalid password. Must be at least 8 characters";
IsValidPassword = false;
ShowPasswordErrorMessage = true;
}
return Task.CompletedTask;
}
Now we can add it to each Entry associated with our fields and use the Command and StoppedTypingTimeThreshold in XAML.
- UserStoppedTypingBehavior Command: The command to execute when the user has stopped providing input
- UserStoppedTypingBehavior.StoppedTypingTimeThreshold: The time of inactivity in milliseconds after which the command will be executed. We are going to set 500 milliseconds.
Using it in the XAML view:
// Name
<Entry Text="{Binding Name}" Placeholder="Enter Name" HorizontalOptions="FillAndExpand" Keyboard="Text">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior Command="{Binding ValidateNameCommand}" StoppedTypingTimeThreshold="500"/>
</Entry.Behaviors>
</Entry>
// Email <Entry Text="{Binding Email}" Placeholder="Enter Email" HorizontalOptions="FillAndExpand" Keyboard="Email"> <Entry.Behaviors> <toolkit:UserStoppedTypingBehavior Command="{Binding ValidateEmailCommand}" StoppedTypingTimeThreshold="500"/> </Entry.Behaviors> </Entry>
// Password
<Entry Text="{Binding Password}" Placeholder="Enter Password" HorizontalOptions="FillAndExpand" Keyboard="Default" IsPassword="True">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior Command="{Binding ValidatePasswordCommand}" StoppedTypingTimeThreshold="500"/>
</Entry.Behaviors>
</Entry>
6. With very little effort, the result is a very nice mobile form that validates the user’s input automatically, creating a much better user experience.
Check out this video below to see how it works with our recent improvements:
My code for this project is available on GitHub for you to review. Happy coding!