jstuardo
jstuardo

Reputation: 4403

MAUI: custom behavior hangs

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

Answers (1)

Liyun Zhang - MSFT
Liyun Zhang - MSFT

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

Related Questions