更改条目文本导致Xamarin中出现无限循环

l5tcr1uw  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(120)

我需要根据条目的文本长度更改其掩码和文本。当我更改文本时,会导致无限循环。
查看我的代码:

async void DocNum_TextChanged(System.Object sender, Xamarin.Forms.TextChangedEventArgs e)
{
    string DocNumCopy = Regex.Replace(DocNum.Text,"[^0-9]","");

    if (DocNumCopy.Length > 11)
    {
        if (DocNumMask.Mask != "XX.XXX.XXX/XXXX-XX")
        {
            DocNum.TextChanged -= DocNum_TextChanged;
            DocNum.Text = DocNumCopy;
            DocNumMask.Mask = "XX.XXX.XXX/XXXX-XX";
            DocNum.TextChanged += DocNum_TextChanged;
        }
    }
    else
    {
        if (DocNumMask.Mask != "XXX.XXX.XXX-XX")
        {
            DocNum.TextChanged -= DocNum_TextChanged;
            DocNum.Text = DocNumCopy;
            DocNumMask.Mask = "XXX.XXX.XXX-XX";
            DocNum.TextChanged += DocNum_TextChanged;
        }
    }
}

我的XAML:

<Frame Padding="2" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" CornerRadius="5">
    <Entry x:Name="DocNum" Text="" Placeholder="CPF/CNPJ" FontSize="18" TextColor="#8C8C8C" TextChanged="DocNum_TextChanged">
        <Entry.Behaviors>
            <ContentView:MaskedBehavior x:Name="DocNumMask" Mask="XXX.XXX.XXX-XX" />
        </Entry.Behaviors>
    </Entry>
</Frame>

掩码代码:

using System.Collections.Generic;
using Xamarin.Forms;

namespace MasterDetailPageNavigation.XAML
{
    public class MaskedBehavior : Behavior<Entry>
    {
        private string _mask = "";
        public string Mask
        {
            get => _mask;
            set
            {
                _mask = value;
                SetPositions();
            }
        }

        protected override void OnAttachedTo(Entry entry)
        {
            entry.TextChanged += OnEntryTextChanged;
            base.OnAttachedTo(entry);
        }

        protected override void OnDetachingFrom(Entry entry)
        {
            entry.TextChanged -= OnEntryTextChanged;
            base.OnDetachingFrom(entry);
        }

        IDictionary<int, char> _positions;

        void SetPositions()
        {
            if (string.IsNullOrEmpty(Mask))
            {
                _positions = null;
                return;
            }

            var list = new Dictionary<int, char>();
            for (var i = 0; i < Mask.Length; i++)
                if (Mask[i] != 'X')
                    list.Add(i, Mask[i]);

            _positions = list;
        }

        private void OnEntryTextChanged(object sender, TextChangedEventArgs args)
        {
            var entry = sender as Entry;

            var text = entry.Text;

            if (string.IsNullOrWhiteSpace(text) || _positions == null)
                return;

            if (text.Length > _mask.Length)
            {
                entry.Text = text.Remove(text.Length - 1);
                return;
            }

            foreach (var position in _positions)
                if (text.Length >= position.Key + 1)
                {
                    var value = position.Value.ToString();
                    if (text.Substring(position.Key, 1) != value)
                        text = text.Insert(position.Key, value);
                }

            if (entry.Text != text)
                entry.Text = text;
        }
    }
}

编辑1:

DocNum是客户的单据编号。根据位数的不同,它应具有不同的掩码,如果编号的字符数为11个或更少,则掩码应为000.000.000-00;但是,如果编号的字符数超过11个,则掩码应为00.000.000/0000-00。
DocNumCopy只是一个没有掩码的DocNum的副本,以便于了解字符的真实的长度。

laik7k3q

laik7k3q1#

已通过移除Entry行为并更改TextChanged的代码来修复此问题,方法如下:

async void DocNum_TextChanged(System.Object sender, Xamarin.Forms.TextChangedEventArgs e)
        {
            var ev = e as TextChangedEventArgs;
            if (ev.NewTextValue != ev.OldTextValue)
            {
                var entry = (Entry)sender;
                string text = Regex.Replace(ev.NewTextValue, @"[^0-9]", "");

                text = text.PadRight(11);

                if(text.Length<=11)
                    text = text.Insert(3, ".").Insert(7, ".").Insert(11, "-").TrimEnd(new char[] { ' ', '.', '-' });
                else if (text.Length > 11)
                {
                    text = text.PadRight(14);
                    text = text.Insert(2, ".").Insert(6, ".").Insert(10, "/").Insert(15, "-").TrimEnd(new char[] { ' ', '.', '-' });
                    if (entry.Text != text)
                        entry.Text = text;
                }

                if (entry.Text != text)
                    entry.Text = text;
            }
}

因此,如果您需要为特定条目设置不同的行为,最简单的方法可能是这样做。

67up9zun

67up9zun2#

在我的例子中,是因为e.NewTextValue = '03'。因为前导零,TextChanged事件进入无限循环。
所以解决办法是

public void OnTextChanged(object sender, TextChangedEventArgs e){
    if(e.NewTextValue.ContainLeadingZero())
    return;
    ....
}

    public static bool ContainLeadingZero(this string value)
    {
        if (value == null)
            return false;            

        if (value.StartsWith("0"))
            return true;

        return false;
    }

相关问题