在我的表单中,我有3个entry控件。我试图用以下验证规则验证“Age”控件:
为此,我将控件的“TextChanged”属性设置为
TextChanged="OnAgeTextChanged"我的OnAgeTextChanged方法是:
private void OnAgeTextChanged(object sender, TextChangedEventArgs e)
{
var entry = (Entry)sender;
try
{
if (entry.Text.Length > 3)
{
string entryText = entry.Text;
entry.TextChanged -= OnAgeTextChanged;
entry.Text = e.OldTextValue;
entry.TextChanged += OnAgeTextChanged;
}
string strName = entry.Text;
if (strName.Contains(".") || strName.Contains("-"))
{
strName = strName.Replace(".", "").Replace("-", "");
entry.Text = strName;
}
}
catch(Exception ex)
{
Console.WriteLine("Exception caught: {0}", ex);
}
}但是,当满足if条件时,事件会被多次循环,导致应用程序运行缓慢。
例如,如果我进入1234岁,它会多次遍历代码,因此会出现延迟,每次更改文本时,延迟都会增加。
除了不多次调用事件之外,还有什么其他方法可以实现此验证?
编辑
在更新代码以删除我的控件上的TextChanged触发器之后,在方法的末尾重新分配它之后,它仍然循环多次,并且循环的数量随着按键的增加而增加。
入口控制xaml
<Entry x:Name="txtAge"
Placeholder="Age"
Keyboard="Numeric"
TextColor="DarkBlue"
PlaceholderColor="DarkBlue"
Completed="AgeCompleted"
HorizontalOptions="Start"
WidthRequest="55"
TextChanged="OnAgeTextChanged"
/>TextChanged事件
private void OnAgeTextChanged(object sender, TextChangedEventArgs e)
{
var entry = (Entry)sender;
try
{
entry.TextChanged -= OnAgeTextChanged;
if (entry.Text.Length > 3)
{
entry.Text = e.OldTextValue;
}
string strName = entry.Text;
if (strName.Contains(".") || strName.Contains("-"))
{
strName = strName.Replace(".", "").Replace("-", "");
entry.Text = strName;
}
}
catch(Exception ex)
{
Console.WriteLine("Exception caught: {0}", ex);
}
finally
{
entry.TextChanged += OnAgeTextChanged;
}
}发布于 2018-06-19 14:27:41
我最终解决这个问题的方法是使用一个单独的类来处理我的验证。
我的验证课:
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class viewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string age_;
public string Age { get { return age_; } set { if (age_ != value) { age_ = ProcessAge(value); OnPropertyChanged(); } } }
private string ProcessAge(string age)
{
if (string.IsNullOrEmpty(age))
return age;
if (age.Length > 3)
age = age.Substring(0, 3);
if (age.StartsWith("0"))
age = age.Remove(0, 1);
return age.Replace(".", "").Replace("-", "");
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}然后,我可以将表单绑定到使用这个类,并使用:
public MainPage()
{
InitializeComponent();
BindingContext = new viewModel();
}最后,为了绑定条目控件以使用Age属性,我设置了Text属性
Text="{Binding Age, Mode=TwoWay}"现在所做的是,每当年龄控件中的值发生变化时,它都会查看新类中的Age属性,并看到要设置它,它需要通过ProcessAge来验证它,这就是现在进行检查的地方。
这更快,因为它只发生一次每键按,不需要摆弄与订阅和取消订阅TextChanged事件和没有循环。
发布于 2018-06-18 16:10:47
看起来,您从事件中收到的object sender与XAML生成的Entry的实例不完全相同。
因此,这可以解释这个问题:
entry.TextChanged -= OnTextChanged;对您的代码没有任何影响,这个对象还没有订阅服务器。
然后,在你的东西的末尾,你设置:
现在是
entry.TextChanged += OnAgeTextChanged;了。您正在“永久化”此实例(sender)。
我想知道这是否是解决您的特定问题的一种优雅的方法(稍后我将尝试发布一些替代方案,如果可以的话),但是要使其正常工作,我想您可以尝试通过txtAge对象引用重新取消订阅和订阅:
private void OnAgeTextChanged(object sender, TextChangedEventArgs e)
{
try
{
txtAge.TextChanged -= OnAgeTextChanged;
if (e.NewTextValue?.Length > 3 ?? false)
txtAge.Text = e.OldTextValue;
string strNumber = txtAge.Text;
if (strNumber.Contains(".") || strNumber.Contains("-"))
{
strNumber = strNumber.Replace(".", "").Replace("-", "");
txtAge.Text = strNumber;
}
}
catch(Exception ex)
{
Console.WriteLine("Exception caught: {0}", ex);
}
finally
{
txtAge.TextChanged += OnAgeTextChanged;
}
}希望能帮上忙。
发布于 2018-06-15 15:34:22
这应该可以解决你的问题:
private void OnAgeTextChanged(object sender, TextChangedEventArgs e)
{
var entry = (Entry)sender;
entry.TextChanged -= OnAgeTextChanged;
try
{ //[...] Your stuff
}
catch(Exception ex)
{
//[...] Your other stuff
}
finally{
entry.TextChanged += OnAgeTextChanged;
}
}因为在下面的代码中,您在事件处理程序仍在侦听时更改文本,因此它至少会再次被触发一次。
if (strName.Contains(".") || strName.Contains("-"))
{
strName = strName.Replace(".", "").Replace("-", "");
entry.Text = strName;
}https://stackoverflow.com/questions/50878023
复制相似问题