Dav*_*vid 6 c# logic android xamarin xamarin.forms
在我的表格上,我有3个entry控件。我正在尝试使用以下验证规则来验证“年龄”控件:
输入的数字不能超过3位
无法输入小数点(。)
无法输入连字符(-)
为此,我将控件的'TextChanged'属性设置为
TextChanged="OnAgeTextChanged"
Run Code Online (Sandbox Code Playgroud)
我的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);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果满足if条件,则该事件将被循环多次,从而导致应用程序运行缓慢。
例如,如果我输入我的年龄为1234,它将多次遍历代码,因此会有延迟,每次更改文本时延迟都会增加。
在没有多次调用事件的情况下,我还能通过什么其他方式来实现此验证?
编辑
更新代码以删除TextChanged控件上的触发器,然后在方法末尾重新分配该触发器之后,它仍会循环多次,并且每次按下键时循环次数都会增加。
进入控制 xaml
<Entry x:Name="txtAge"
Placeholder="Age"
Keyboard="Numeric"
TextColor="DarkBlue"
PlaceholderColor="DarkBlue"
Completed="AgeCompleted"
HorizontalOptions="Start"
WidthRequest="55"
TextChanged="OnAgeTextChanged"
/>
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我最终解决这个问题的方法是使用一个单独的类来处理我的验证。
我的验证类:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我可以绑定表单以使用此类,使用:
public MainPage()
{
InitializeComponent();
BindingContext = new viewModel();
}
Run Code Online (Sandbox Code Playgroud)
最后,为了绑定入口控件以使用 Age 属性,我设置了Text属性
Text="{Binding Age, Mode=TwoWay}"
Run Code Online (Sandbox Code Playgroud)
现在所做的是,每次 Age 控件中的值发生变化时,它都会查看新类中的 Age 属性并查看是否要设置它,需要通过ProcessAge验证来验证它,这就是检查的位置现在完成了。
这更快,因为它每次按键只发生一次,并且订阅和取消订阅TextChanged事件不需要摆弄,也没有循环。
看来您从事件中收到的实例与您的 生成的object sender实例不完全相同。EntryXAML
那么,这就可以解释这个问题了:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望它有帮助。
| 归档时间: |
|
| 查看次数: |
3609 次 |
| 最近记录: |