Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Forms Password and Confirm Password Validation

I have a Xamarin Forms application in which I have a registration form in which I need to validate Password and Confirm Password fields should be same.

Is there any way to implement this using Xamarin Behaviour?

I have already implemented Xamarin Behaviour for Required Field validation and Email Regex validation like this below-

public class RequiredValidatorBehavior : Behavior<Entry>
    {
        static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(RequiredValidatorBehavior), false);
        static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

        public bool IsValid
        {
            get { return (bool)base.GetValue(IsValidProperty); }
            private set { base.SetValue(IsValidPropertyKey, value); }
        }

        protected override void OnAttachedTo(Entry bindable)
        {
            bindable.Unfocused += HandleFocusChanged;
            base.OnAttachedTo(bindable);
        }
        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.Unfocused -= HandleFocusChanged;
            base.OnDetachingFrom(bindable);
        }
        void HandleFocusChanged(object sender, FocusEventArgs e)
        {
            IsValid = !string.IsNullOrEmpty (((Entry)sender).Text);
        }
    }

Implementation of Behaviour in XAML Content Page-

<Entry x:Name="password" Placeholder="New Password">
    <Entry.Behaviors>
        <local:RequiredValidatorBehavior x:Name="passwordValidator"/>   
    </Entry.Behaviors>
</Entry>

The problem is - I am new in Xamarin development and have no idea how can I get the value of both Password and Confirm Password fields in Behaviour so that I can compare them. I do not wish to compare them on click of button when the form is submitted, fields should be compared while the user is typing in the fields. Any code, help or guidance is appreciable.

like image 641
Manik Arora Avatar asked Dec 08 '22 02:12

Manik Arora


2 Answers

https://forums.xamarin.com/discussion/34695/xaml-how-do-you-pass-a-control-view-reference-into-a-behavior

This will help you. You will use Compare Validator behavior for this as following.

<behaviors:CompareValidator x:Name="ComparePasswordsValidator" 
        CompareToEntry="{Binding Source={x:Reference PasswordEntry}}" /> 

Finally The Solution:

XAML-

<Entry x:Name="password" Placeholder="New Password" IsPassword="true">
    <Entry.Behaviors>
        <local:RequiredValidatorBehavior x:Name="passwordValidator"/>   
    </Entry.Behaviors>
</Entry>
<Entry x:Name="confirmPassword" Placeholder="Confirm Password" IsPassword="true">
    <Entry.Behaviors>
        <local:ConfirmPasswordBehavior x:Name="confirmPasswordBehavior" CompareToEntry="{Binding Source={x:Reference password}}" />
    </Entry.Behaviors>
</Entry>

BEHAVIOR-

    public class ConfirmPasswordBehavior : Behavior<Entry>
    {
        static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(ConfirmPasswordBehavior), false);
        public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

        public static readonly BindableProperty CompareToEntryProperty = BindableProperty.Create("CompareToEntry", typeof(Entry), typeof(ConfirmPasswordBehavior), null);

        public Entry CompareToEntry
        {
            get { return (Entry)base.GetValue(CompareToEntryProperty); }
            set { base.SetValue(CompareToEntryProperty, value); }
        }
        public bool IsValid
        {
            get { return (bool)base.GetValue(IsValidProperty); }
            private set { base.SetValue(IsValidPropertyKey, value); }
        }
        protected override void OnAttachedTo(Entry bindable)
        {
            bindable.TextChanged += HandleTextChanged;
            base.OnAttachedTo(bindable);
        }
        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.TextChanged -= HandleTextChanged;
            base.OnDetachingFrom(bindable);
        }
        void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            var password = CompareToEntry.Text;
            var confirmPassword = e.NewTextValue;
            IsValid = password.Equals (confirmPassword);
        }
    }
like image 156
Puneet Avatar answered Jan 15 '23 19:01

Puneet


I've make some changes on Punnet answer:

First, to fix the null exception on HandleTextChanged that was thrown when the comparable string was null

    void HandleTextChanged(object sender, TextChangedEventArgs e)
    {
        string theBase = CompareToEntry.Text;
        string confirmation = e.NewTextValue;
        // here is the change
        IsValid = (bool)theBase?.Equals(confirmation);

        ((Entry)sender).TextColor = IsValid ? Color.Green : Color.Red;
    }

And the second was to check if the comparable string was changed after the validation becomes true.

    void baseValue_changed(object sender, TextChangedEventArgs e)
    {
        IsValid = (bool)((Entry)sender).Text?.Equals(thisEntry.Text);
        thisEntry.TextColor = IsValid ? Color.Green : Color.Red;
    }

So the new code become

public class ComparisonBehavior : Behavior<Entry>
{
    private Entry thisEntry;

    static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(ComparisonBehavior), false);
    public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

    public static readonly BindableProperty CompareToEntryProperty = BindableProperty.Create("CompareToEntry", typeof(Entry), typeof(ComparisonBehavior), null);

    public Entry CompareToEntry
    {
        get { return (Entry)base.GetValue(CompareToEntryProperty); }
        set
        {
            base.SetValue(CompareToEntryProperty, value);
            if (CompareToEntry != null)
                CompareToEntry.TextChanged -= baseValue_changed;
            value.TextChanged += baseValue_changed;
        }
    }

    void baseValue_changed(object sender, TextChangedEventArgs e)
    {
        IsValid = ((Entry)sender).Text.Equals(thisEntry.Text);
        thisEntry.TextColor = IsValid ? Color.Green : Color.Red;
    }


    public bool IsValid
    {
        get { return (bool)base.GetValue(IsValidProperty); }
        private set { base.SetValue(IsValidPropertyKey, value); }
    }
    protected override void OnAttachedTo(Entry bindable)
    {
        thisEntry = bindable;

        if (CompareToEntry != null)
            CompareToEntry.TextChanged += baseValue_changed;

        bindable.TextChanged += HandleTextChanged;
        base.OnAttachedTo(bindable);
    }

    protected override void OnDetachingFrom(Entry bindable)
    {
        bindable.TextChanged -= HandleTextChanged;
        if (CompareToEntry != null)
            CompareToEntry.TextChanged -= baseValue_changed;
        base.OnDetachingFrom(bindable);
    }

    void HandleTextChanged(object sender, TextChangedEventArgs e)
    {
        string theBase = CompareToEntry.Text;
        string confirmation = e.NewTextValue;
        IsValid = (bool)theBase?.Equals(confirmation);

        ((Entry)sender).TextColor = IsValid ? Color.Green : Color.Red;
    }
}
like image 41
Nicollas Braga Avatar answered Jan 15 '23 19:01

Nicollas Braga