Behavior Validation in Xamarin Form

 Xamarin.Forms Behaviors are created by deriving from the Behavior or Behavior<T> class, where T is the type of the control (Entry, etc) to which the Behavior should apply.

Create a new class and which inherits from the Behavior or Behavior<T> class.

We need to override OnAttachedTo and OnDetachingFrom method from our validation class.

The OnAttachedTo method is fired immediately after the behavior is attached to a control. This can be used to register event handlers or perform other setup that's required to support the behavior functionality.

The OnDetachingFrom method is fired when the behavior is removed from the control. This method receives a reference to the control to which it is attached, and is used to perform any required cleanup.

Register.xaml

    <ContentPage.Resources>
        <ResourceDictionary>

            <Style x:Key="baseStyle"
             TargetType="Label">
                <Setter Property="XAlign" Value="Start" />
                <Setter Property="YAlign" Value="Start" />
                <Setter Property="FontSize" Value="Small" />
                <Setter Property="FontAttributes" Value="None" />
            </Style>
            <local:BooleanToObjectConverter x:Key="boolToStyleEmail"
                                           x:TypeArguments="Style">
                <local:BooleanToObjectConverter.FalseObject>
                    <Style TargetType="Label" BasedOn="{StaticResource baseStyle}">
                        <Setter Property="TextColor" Value="#F44336" />
                        <Setter Property="Text" Value="Enter a valid email" />
                    </Style>
                </local:BooleanToObjectConverter.FalseObject>

            </local:BooleanToObjectConverter>
            <local:BooleanToObjectConverter x:Key="boolToStylePassword"
                                           x:TypeArguments="Style">
                <local:BooleanToObjectConverter.FalseObject>
                    <Style TargetType="Label" BasedOn="{StaticResource baseStyle}">
                        <Setter Property="TextColor" Value="#F44336" />
                        <Setter Property="Text" Value="Password should have 1 Capital Letter, 1 Small Letter, 1 number, 1 Symbol" />
                    </Style>
                </local:BooleanToObjectConverter.FalseObject>
            </local:BooleanToObjectConverter>
            <local:BooleanToObjectConverter x:Key="boolToStyleConfirmPassword"
                                           x:TypeArguments="Style">
                <local:BooleanToObjectConverter.FalseObject>
                    <Style TargetType="Label" BasedOn="{StaticResource baseStyle}">
                        <Setter Property="TextColor" Value="#F44336" />
                        <Setter Property="Text" Value="Password and Confirm Password does not match." />
                    </Style>
                </local:BooleanToObjectConverter.FalseObject>
            </local:BooleanToObjectConverter>


        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Image Grid.Row="0" Margin="0,30" Source="xamarinlogo.png" Aspect="AspectFit" HeightRequest="180" WidthRequest="80"></Image>
            <Frame Grid.Row="1" Margin="0,0,0,-40" BorderColor="#1C375C" HasShadow="True"  CornerRadius="50" HeightRequest="700">
                <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" RowSpacing="10" Padding="20,50,20,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Label Grid.Row="0" Margin="0,-20,0,0"  Text="Sign Up" FontSize="24" FontAttributes="Bold" TextColor="#1C375C" HorizontalOptions="CenterAndExpand"></Label>
                    <Entry x:Name="txtFirstName" Grid.Row="1" Placeholder="First Name"  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></Entry>
                    <Entry x:Name="txtLastName" Grid.Row="2" Placeholder="Last Name"  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></Entry>
                    <Entry x:Name="txtEmail" Grid.Row="3" Placeholder="Email"  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                        <Entry.Behaviors>
                            <local:EmailValidatorBehavior x:Name="emailValidator"/>
                        </Entry.Behaviors>
                    </Entry>
                    <Label x:Name="lblValEmal" Grid.Row="4" HeightRequest="20" Style="{Binding Source={x:Reference emailValidator}, 
                                Path=IsValid,   Converter={StaticResource boolToStyleEmail}}" />
                    <Entry x:Name="txtPassword" Grid.Row="5" Placeholder="Password" IsPassword="True" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                        <Entry.Behaviors>
                            <local:PasswordValidationBehavior x:Name="passwordValidator"/>
                        </Entry.Behaviors>
                    </Entry>
                    <Label x:Name="lblValPassword" Grid.Row="6" FontSize="Micro" HeightRequest="20" Style="{Binding Source={x:Reference passwordValidator}, 
                                Path=IsValid,  Converter={StaticResource boolToStylePassword}}" />
                    <Entry x:Name="txtConfirmPassword" Grid.Row="7" Placeholder="Confirm Password" IsPassword="True" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                        <Entry.Behaviors>
                            <local:CompareValidationBehavior x:Name="confirmPasswordValidator" 
                             BindingContext="{x:Reference txtPassword}" Text="{Binding Text}"/>
                        </Entry.Behaviors>
                    </Entry>
                    <Label x:Name="lblValConfirmPassword" Grid.Row="8" FontSize="Micro" HeightRequest="20" Style="{Binding Source={x:Reference confirmPasswordValidator}, 
                                Path=IsValid,  Converter={StaticResource boolToStyleConfirmPassword}}" />
                    
                    <Button x:Name="btnRegister" Grid.Row="9" Text="Register" Clicked="btnRegister_Clicked" BackgroundColor="#1C375C" CornerRadius="20"></Button>

                    <Label Grid.Row="10" Margin="0,-10,0,0" Text="Already have an account? Sign in here" HorizontalOptions="CenterAndExpand"></Label>


                </Grid>
            </Frame>
        </Grid>
    </ContentPage.Content>  

PasswordValidationBehavior.cs

The code, given below is Password validation Behaviors. Password rule should contain at least 8 characters, 1 numeric, 1 lowercase, 1 uppercase, 1 special character [eg: Xamarin#123]

    public class PasswordValidationBehavior : Behavior<Entry>
    {
        const string passwordRegex = @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$";
        static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(PasswordValidationBehavior), false);
public 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.TextChanged += HandleTextChanged; base.OnAttachedTo(bindable); } void HandleTextChanged(object sender, TextChangedEventArgs e) { IsValid = false; IsValid = (Regex.IsMatch(e.NewTextValue, passwordRegex)); ((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red; } protected override void OnDetachingFrom(Entry bindable) { bindable.TextChanged -= HandleTextChanged; base.OnDetachingFrom(bindable); } }

BooleanToObjectConverter.cs

    public class BooleanToObjectConverter<T> : IValueConverter
    {
        public T FalseObject { set; get; }

        public T TrueObject { set; get; }


        public object Convert(object value, Type targetType,
                              object parameter, CultureInfo culture)
        {
            return (bool)value ? this.TrueObject : this.FalseObject;
        }

        public object ConvertBack(object value, Type targetType,
                                  object parameter, CultureInfo culture)
        {
            return ((T)value).Equals(this.TrueObject);
        }
    }  

CompareValidationBehavior.cs

    public class CompareValidationBehavior : Behavior<Entry>
    {

        public static BindableProperty TextProperty = BindableProperty.Create<CompareValidationBehavior, string>(tc => tc.Text, string.Empty, BindingMode.TwoWay);
        static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(CompareValidationBehavior), false);

        public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

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


        protected override void OnAttachedTo(Entry bindable)
        {
            bindable.TextChanged += HandleTextChanged;
            base.OnAttachedTo(bindable);
        }

        void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            IsValid = e.NewTextValue == Text;

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

        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.TextChanged -= HandleTextChanged;
            base.OnDetachingFrom(bindable);
        }
    }

EmailValidatorBehavior.cs

    public class EmailValidatorBehavior : Behavior<Entry>
    {
        const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
            @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$";


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

        public 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.TextChanged += HandleTextChanged;
            base.OnAttachedTo(bindable);
        }


        void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            IsValid = (Regex.IsMatch(e.NewTextValue, emailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
            ((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red;
        }

        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.TextChanged -= HandleTextChanged;
            base.OnDetachingFrom(bindable);

        }
    } 

Please share your feedback

Comments

Post a Comment

Popular posts from this blog

Push Notifications in .NET MAUI: A Comprehensive Guide

Explore the UI libraries available for .NET MAUI at no cost.

Push Notification using Firebase in xamarin form (Android and IOS)