Reputation: 4792
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.
Upvotes: 4
Views: 12928
Reputation: 1
If you want to add exception handling because of System.InvalidOperationException error is showing when typing confirm password first before typing a password.
void HandleTextChanged(object sender, TextChangedEventArgs e)
{
try
{
string theBase = CompareToEntry.Text;
string confirmation = e.NewTextValue;
IsValid = (bool)theBase?.Equals(confirmation);
((Entry)sender).TextColor = IsValid ? Color.FromHex("#e6a94d")/*correct*/ : Color.FromHex("#CD5C5C")/*incorrect*/;
}
catch (System.InvalidOperationException)
{
string theBase = CompareToEntry.Text;
string confirmation = e.NewTextValue;
((Entry)sender).TextColor = IsValid ? Color.FromHex("#e6a94d")/*correct*/ : Color.FromHex("#CD5C5C")/*incorrect*/;
}
}
Upvotes: 0
Reputation: 892
I have developed custom control to validate our model using data annotation method.
Here is project url.
https://github.com/MaulikParmar/XamarinForms/tree/master/ValidationDemo
It is not working for window 8.1 phone.
Here is youtube url for project description and how to use this control more effectively.
https://www.youtube.com/watch?v=eEi-Oky4U08
Upvotes: 2
Reputation: 821
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;
}
}
Upvotes: 3
Reputation: 2051
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);
}
}
Upvotes: 9