The first thing, maybe you should look at this post:
https://blog.xamarin.com/behaviors-in-xamarin-forms/
Base on this, I do some changing code.
- In the real thing, you may like to validate many condition for one controls (such as: Require and email format, require and maxlength...). To make it easier I create validation class to validate for each control type, instead of each rule. Let's see the code is changed:
1:
3: using Xamarin.Forms;
4:
5: namespace MyProject.Client.Framework.Validators
6: {
7: public class EntryValidatorBehavior : Behavior<Entry>
8: {
9: #region Properties
10:
11: //Result Boolean
12: private static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid",
13: typeof(bool), typeof(EntryValidatorBehavior), false);
14:
15: public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;
16:
17: public bool IsValid
18: {
19: get { return (bool)GetValue(IsValidProperty); }
20: private set { SetValue(IsValidPropertyKey, value); }
21: }
22:
23: //Result message
24: public static readonly BindableProperty MessageProperty = BindableProperty.Create("Message",
25: typeof(string), typeof(EntryValidatorBehavior), string.Empty);
26:
27: public string Message
28: {
29: get { return (string)GetValue(MessageProperty); }
30: private set { SetValue(MessageProperty, value); }
31: }
32:
33: //Is check empty
34: public static BindableProperty IsCheckEmptyProperty = BindableProperty.Create("IsCheckEmpty",
35: typeof(bool), typeof(EntryValidatorBehavior), false);
36:
37: public bool IsCheckEmpty
38: {
39: get { return (bool)GetValue(IsCheckEmptyProperty); }
40: set { SetValue(IsCheckEmptyProperty, value); }
41: }
42:
43: //Is check email
44: public static BindableProperty IsCheckEmailProperty = BindableProperty.Create("IsCheckEmail",
45: typeof(bool), typeof(EntryValidatorBehavior), false);
46:
47: public bool IsCheckEmail
48: {
49: get { return (bool)GetValue(IsCheckEmailProperty); }
50: set { SetValue(IsCheckEmailProperty, value); }
51: }
52:
53: #endregion Properties
54:
55: protected override void OnAttachedTo(Entry bindable)
56: {
57: bindable.TextChanged += HandleTextChanged;
58: }
59:
60: private void HandleTextChanged(object sender, TextChangedEventArgs e)
61: {
62: if (IsCheckEmpty)
63: {
64: IsValid = ValidatorsFactory.IsValidEmpty(e.NewTextValue);
65: Message = Messages.FieldCannotBlank;
66: if (!IsValid)
67: {
68: ((Entry)sender).TextColor = Color.Red;
69: return;
70: }
71: }
72: if (IsCheckEmail)
73: {
74: IsValid = ValidatorsFactory.IsValidEmail(e.NewTextValue);
75: Message = Messages.EmailIncorrectFormat;
76: if (!IsValid)
77: {
78: ((Entry)sender).TextColor = Color.Red;
79: return;
80: }
81: }
82: //TODO: add more validation
83:
84: //Default
85: IsValid = true;
86: Message = string.Empty;
87: ((Entry)sender).TextColor = AppColors.EntryTextColor;
88: }
89:
90: protected override void OnDetachingFrom(Entry bindable)
91: {
92: bindable.TextChanged -= HandleTextChanged;
93: }
94: }
95: }
* Note: It's contain some constants and reference to my source code so if you just copy&paste, it will not work, let's try to understand it.
Some thing changed here:
- The first thing I add Message property to provide different validate message of each error for client to display. You see I set value for the Message in HandleTextChanged method.
- Each kind of validate will have an option to validate it or not. In my code you will see: IsCheckEmpty, IsCheckEmail that you can control what you wanna validate for Entry or not.
- The HandleTextChanged method ( or handle another event) will do validate and set value for IsValid and Message. You may wonder what is ValidatorsFactory, that the logic of validate I moved to other class call ValidatorsFactory.
Let's see how that factory work:
1: using System;
2: using System.Text.RegularExpressions;
3:
4: namespace MyProject.Client.Framework.Validators
5: {
6: public static class ValidatorsFactory
7: {
8: private const string EmailRegex =
9: @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
10: @"(?(\[)(\[(\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]))$";
11:
12: public static bool IsValidEmail(string input)
13: {
14: return (Regex.IsMatch(input, EmailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
15: }
16:
17: public static bool IsValidEmpty(string input)
18: {
19: return !string.IsNullOrWhiteSpace(input);
20: }
21:
22: public static bool IsValidMaxlength(string input, int maxlength)
23: {
24: return input.Length <= maxlength;
25: }
26:
27: //TODO: add more validation
28: }
29: }
Then, how to use. This example I used in sign-in page:
1: <controls:ExtendedEntry Grid.Row="0" Keyboard="Email" Text="{Binding Model.Email, Mode=OneWayToSource}" Placeholder="Email">
2: <Entry.Behaviors>
3: <validators:EntryValidatorBehavior IsCheckEmpty="True" IsCheckEmail="True" x:Name="EmailValidator"/>
4: </Entry.Behaviors>
5: </controls:ExtendedEntry>
6: <Label Grid.Row="1" TextColor="{x:Static styles:AppColors.LabelErrorTextColor}"
7: Text="{Binding Source={x:Reference EmailValidator}, Path=Message}"
8: VerticalOptions="Start" HorizontalOptions="Start"
9: IsVisible="{Binding Source={x:Reference EmailValidator}, Path=IsValid,Converter={StaticResource InvertBoolConverter}}"/>
Thank you for reading.
Edit: Please see the updated version here: http://blog.zquanghoangz.com/?p=139
This looks fantastic! I'm going to try and implement this now :)
ReplyDeleteWhat is Messages in this code?
ReplyDeleteA static class that define string constants of messages.
Deleteya got it thanx ..have used your code..if you have any sample of editable entry inside listview then please upload
Deletethanx in advance :-)
Hi, namespace controls and validators prefix not defined showing on my xaml file, how to solve it. I am new at xamarin.
ReplyDeleteAlso when I build my project Messages and AppColors doesn't exist error is getting here, how to resolve it?
ReplyDeleteHi, it would be really great if you can share the source code.
ReplyDeletePlease see the updated version here: http://blog.zquanghoangz.com/?p=139
ReplyDelete