首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TextChanged事件循环控制

TextChanged事件循环控制
EN

Stack Overflow用户
提问于 2018-06-15 14:53:38
回答 4查看 13.6K关注 0票数 10

在我的表单中,我有3个entry控件。我试图用以下验证规则验证“Age”控件:

  • 不能输入超过3位数字。
  • 无法输入小数位(.)
  • 无法输入连字符(-)

为此,我将控件的“TextChanged”属性设置为

代码语言:javascript
复制
TextChanged="OnAgeTextChanged"

我的OnAgeTextChanged方法是:

代码语言:javascript
复制
 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

代码语言:javascript
复制
<Entry x:Name="txtAge"
       Placeholder="Age"
       Keyboard="Numeric"
       TextColor="DarkBlue"
       PlaceholderColor="DarkBlue"
       Completed="AgeCompleted"
       HorizontalOptions="Start"
       WidthRequest="55"
       TextChanged="OnAgeTextChanged"
/>

TextChanged事件

代码语言:javascript
复制
 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;
        }
     }
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-06-19 14:27:41

我最终解决这个问题的方法是使用一个单独的类来处理我的验证。

我的验证课:

代码语言:javascript
复制
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));
 }
}

然后,我可以将表单绑定到使用这个类,并使用:

代码语言:javascript
复制
public MainPage()
    {
        InitializeComponent();
        BindingContext = new viewModel();
    }

最后,为了绑定条目控件以使用Age属性,我设置了Text属性

代码语言:javascript
复制
Text="{Binding Age, Mode=TwoWay}"

现在所做的是,每当年龄控件中的值发生变化时,它都会查看新类中的Age属性,并看到要设置它,它需要通过ProcessAge来验证它,这就是现在进行检查的地方。

这更快,因为它只发生一次每键按,不需要摆弄与订阅和取消订阅TextChanged事件和没有循环。

票数 6
EN

Stack Overflow用户

发布于 2018-06-18 16:10:47

看起来,您从事件中收到的object senderXAML生成的Entry的实例不完全相同。

因此,这可以解释这个问题:

entry.TextChanged -= OnTextChanged;对您的代码没有任何影响,这个对象还没有订阅服务器。

然后,在你的东西的末尾,你设置:

现在是entry.TextChanged += OnAgeTextChanged;了。您正在“永久化”此实例(sender)。

我想知道这是否是解决您的特定问题的一种优雅的方法(稍后我将尝试发布一些替代方案,如果可以的话),但是要使其正常工作,我想您可以尝试通过txtAge对象引用重新取消订阅和订阅:

代码语言:javascript
复制
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;
    }
 }

希望能帮上忙。

票数 5
EN

Stack Overflow用户

发布于 2018-06-15 15:34:22

这应该可以解决你的问题:

代码语言:javascript
复制
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;
    }
}

因为在下面的代码中,您在事件处理程序仍在侦听时更改文本,因此它至少会再次被触发一次。

代码语言:javascript
复制
if (strName.Contains(".") || strName.Contains("-"))
{
    strName = strName.Replace(".", "").Replace("-", "");
    entry.Text = strName;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50878023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档