What is the best way to validate a TextBox XAML

7

I have a UWP application that uses several TextBox to collect user information:

<Grid>
    <TextBox Text="{Binding Codigo}"></TextBox>
    <TextBox Text="{Binding Producto}"></TextBox>
    <TextBox Text="{Binding Cantidad}"></TextBox>
</Grid>

My question, what is the best way to validate that the user does not enter incorrect data, that is, make TextBox only allow entering numbers or some type of character mask?

It must be done from code or it can be done from XAML

    
asked by Edwin V 16.01.2016 в 01:07
source

2 answers

7

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.

UWP - How to implement validation of fields in Universal Apps

    
answered by 18.01.2016 / 04:57
source
0

You could use DataAnnotations , adding the reference to System.ComponentModel.DataAnnotations

Basically, in your ViewModel you define the attribute on the property that you binde the control in the view:

public class xxViewModel : ViewModelBase {

    //resto propiedades

    [Required(ErrorMessage = "Debe ingresar una cantidad")] 
    public int Cantidad {get;set;}

}

For more detail I recommend this article Validation in MVVM using Data Annotations , It is very complete

Because it is a UWP application, the DataAnnotations library may not let you reference it, but following the same path there is an alternative with:

Basically it's the same, you define validation attributes in the properties of the ViewModel , only that you would use a suitable implementation to WinRT.

    
answered by 16.01.2016 в 01:18