Reputation: 4403
I have this custom behavior attached to an Entry
field:
public partial class SsnValidationBehavior : TextValidationBehavior
{
public static readonly BindableProperty Iso2CountryProperty = BindableProperty.Create(nameof(Iso2Country), typeof(string), typeof(SsnValidationBehavior), "cl");
public string Iso2Country
{
get => (string)GetValue(Iso2CountryProperty);
set => SetValue(Iso2CountryProperty, value);
}
public static bool ChileValidate(string docNumber)
{
string rut = CleanRegex().Replace(docNumber, string.Empty).ToUpper();
if (rut.Length >= 2)
{
string dv = rut[rut.Length - 1].ToString();
if (MatchRegex().IsMatch(dv))
{
int largo = rut.Length;
if (largo > 10 || largo < 2) return false;
// La parte del RUT debe ser un número entero
if (int.TryParse(rut.AsSpan(0, largo - 1), out _))
{
// El dígito verificador debe ser un número o la K
if ((rut[largo - 1].CompareTo('0') < 0 || rut[largo - 1].CompareTo('9') > 0) && rut[largo - 1] != 'K')
return false;
// Realiza la operación módulo
int suma = 0;
int mul = 2;
// -2 porque rut contiene el dígito verificador, el cual no hay que considerar
for (int i = rut.Length - 2; i >= 0; i--)
{
suma += int.Parse(rut[i].ToString()) * mul;
if (mul == 7) mul = 2; else mul++;
}
int residuo = suma % 11;
char dvr;
if (residuo == 1)
dvr = 'K';
else if (residuo == 0)
dvr = '0';
else
dvr = (11 - residuo).ToString()[0];
return dvr.Equals(rut[^1]);
}
}
}
return false;
}
protected override async ValueTask<bool> ValidateAsync(string value, CancellationToken token)
{
bool result = true;
string iso2 = Iso2Country ?? string.Empty;
switch (iso2)
{
case "cl":
result = ChileValidate(value);
break;
}
return result && await base.ValidateAsync(value, token);
}
[GeneratedRegex("[ .-]")]
private static partial Regex CleanRegex();
[GeneratedRegex("[0-9K]")]
private static partial Regex MatchRegex();
}
When I press any key in the field, the app hangs (even Visual Studio). I placed a breakpoint at ValidateAsync
but it is not reached.
I took the model of this behavior from https://github.com/CommunityToolkit/Maui/blob/main/src/CommunityToolkit.Maui/Behaviors/Validators/EmailValidationBehavior.shared.cs
Any help?
Upvotes: 0
Views: 149
Reputation: 14434
Frist of all, I have created a new project to test your custom behavior. But I can't reproduce your problem. There is the code:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp4.NewPage2"
xmlns:mybehavior="clr-namespace:MauiAppTest"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
Title="NewPage2">
<ContentPage.Resources>
<Style x:Key="InvalidEntryStyle" TargetType="Entry">
<Setter Property="TextColor" Value="Blue" />
</Style>
<Style x:Key="ValidEntryStyle" TargetType="Entry">
<Setter Property="TextColor" Value="Green" />
</Style>
</ContentPage.Resources>
<Entry x:Name="entry">
<Entry.Behaviors>
<mybehavior:SsnValidationBehavior
InvalidStyle="{StaticResource InvalidEntryStyle}"
ValidStyle="{StaticResource ValidEntryStyle}"
Flags="ValidateOnValueChanged"
MinimumLength="1"
MaximumLength="10" />
</Entry.Behaviors>
</Entry>
</ContentPage>
And I have added the break point at the ValidateAsync
and it can be hit. First, I saw the value of the iso2
and Iso2Country
always be cl
(default value), so the result && await base.ValidateAsync(value, token)
always be false. It seems you never called the Iso2Country's setter method.
In addition, I also check your last question. If you want to check the entry's text is null or empty. You can use the datatrigger to do that. Such as:
<Entry x:Name="entry">
<Entry.Triggers>
<DataTrigger TargetType="Entry" Binding="{Binding Source={x:Reference entry}, Path=Text}" Value="{x:Null}">
<Setter Property="BackgroundColor" Value="Pink"/>
</DataTrigger>
<DataTrigger TargetType="Entry" Binding="{Binding Source={x:Reference entry}, Path=Text.Length}" Value="0">
<Setter Property="BackgroundColor" Value="Pink"/>
</DataTrigger>
</Entry.Triggers>
</Entry>
Upvotes: 1