更改条目文本导致 Xamarin 中的无限循环
Change Entry Text is causing infinite loop in Xamarin
我需要根据文本长度更改条目的掩码和文本。当我更改文本时,它会导致无限循环。
查看我的代码:
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 的副本,以便于了解字符的真实长度。
已通过删除 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;
}
}
因此,如果您需要对特定条目有不同的行为,也许最简单的方法就是这样做。
我需要根据文本长度更改条目的掩码和文本。当我更改文本时,它会导致无限循环。
查看我的代码:
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 的副本,以便于了解字符的真实长度。
已通过删除 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;
}
}
因此,如果您需要对特定条目有不同的行为,也许最简单的方法就是这样做。