Currently UWP
does not include any validation framework, however the C # community is thriving and on GitHub there is already a very interesting alternative that is worth reviewing: ValidatableBase to use it you must download the GitHub code and compile the library and then add it to the solution.
The model
what you have to do is create a model that inherits from ValidatableBase
, as you are probably using BindableBase
would you prefer to use something like this
using Sullinger.ValidatableBase.Models;
public class User
{
BindableBase binder;
private string name;
public string Name
{
get { return name; }
set { binder.SetProperty(ref name, value); }
}
private string email;
public string Email
{
get { return email; }
set { binder.SetProperty(ref email, value); }
}
public User()
{
binder = new BindableBase();
email = name = string.Empty;
}
}
The viewModel
To trigger the validation you can do it in many ways but one way is with a button in which case it is convenient to have a ViewModel as well.
public class MainPageVM : BindableBase, ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
throw new NotImplementedException();
}
private User usuario;
public User Usuario
{
get { return usuario; }
set { SetProperty(ref usuario, value); }
}
private string errores;
public string Errores
{
get { return errores; }
set
{ SetProperty(ref errores, value); }
}
public MainPageVM()
{
errores = string.Empty;
usuario = new User();
}
}
XAML and binding
The XAML
with which you must binde is like this
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Nombre: "/>
<TextBox Text="{Binding Usuario.Name, Mode=TwoWay}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Email: "/>
<TextBox Text="{Binding Usuario.Email, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Errores :"/>
<TextBlock Width="400" Height="100" Text="{Binding Errores}" />
</StackPanel>
<Button HorizontalAlignment="Stretch" Command="{Binding}">
Validar
</Button>
</StackPanel>
</Grid>
Adding validation attributes to model properties
Once you have everything ready then you decorate the model with validation attributes, I have included in the example validation of the required field and validation that the email value is indeed an email, making use of a personalized validation.
using System.ComponentModel;
namespace App5.Models
{
using Sullinger.ValidatableBase.Models;
using Sullinger.ValidatableBase.Models.ValidationRules;
using System.Reflection;
using System.Text.RegularExpressions;
public class User : ValidatableBase
{
BindableBase binder;
private string name;
[ValidateObjectHasValue(FailureMessage = "El nombre no se puede dejar en blanco",
ValidationMessageType = typeof(ValidationErrorMessage))]
public string Name
{
get { return name; }
set { binder.SetProperty(ref name, value); }
}
private string email;
[ValidateWithCustomHandler( DelegateName = "IsValidEmail",
FailureMessage = "Esto no parece un correo electrónico",
ValidationMessageType = typeof(ValidationWarningMessage))]
[ValidateObjectHasValue(FailureMessage = "El email no se puede dejar en blanco",
ValidationMessageType = typeof(ValidationErrorMessage))]
public string Email
{
get { return email; }
set { binder.SetProperty(ref email, value); }
}
public User()
{
binder = new BindableBase();
email = name = string.Empty;
}
[ValidationCustomHandlerDelegate(DelegateName = "IsValidEmail")]
private IValidationMessage IsValidEmail(IValidationMessage failureMessage, PropertyInfo property)
{
const string regExp = @"\A(?:[a-z0-9!#$%&'*+/=?^_'{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_'{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z";
return Regex.IsMatch(this.Email, regExp, RegexOptions.IgnoreCase)
? null
: failureMessage;
}
}
}
Processing errors in the ViewModel
Finally in the Viewmodel, implement the Execute
method so that you can put in Errores
all the errors of all the properties of the model, thus remaining
public void Execute(object parameter)
{
Errores = string.Empty;
Usuario.ValidateAll();
if (Usuario.HasValidationMessages())
{
var propiedades = Usuario.GetValidationMessages();
foreach (var propiedad in propiedades)
{
foreach (var error in propiedad.Value)
{
Errores += $"{propiedad.Key}: {error.Message}\n";
}
}
}
}
That will work for you already.
Of course the subject is not difficult, but it is not a topic that can be explained in a very short way because there are many things that are required. In this answer you have the summary of everything, but I guess you can get pretty lost in some parts so I've written a very detailed article in my blog that will guide you step by step in case you need.