我在TextChanged事件中的代码破坏了WPF中的绑定,并导致了非常奇怪的行为

本文关键字:非常 绑定 代码 事件 TextChanged 坏了 我在 WPF | 更新日期: 2023-09-27 18:00:04

在我的VS 2012 WPF项目中,我有一个名为TextBoxDX的自定义文本框类,它添加了AutoSelect功能。没问题。我有另一个基于TextBoxDX的类,名为IntBox,它只允许整数。这就是我们故事的开始。这两个类都用于绑定情况,例如:

<local:TextBoxDX Grid.Row="0" Grid.Column="1" x:Name="txtBox_singlesName" Width="320" HorizontalAlignment="left" Text="{Binding SelectedItem.name, ElementName=listBoxSingles, Mode=OneWay}"/>
<local:IntBox x:Name="intBox_heightin" Width="60" AllowZeroValue="True" MaxLength="2" Text="{Binding SelectedItem.heightin, ElementName=listBoxSingles, Mode=OneWay}" MinVal="0" MaxVal="11"/>

可以肯定的是,除了绑定之外,大部分内容都无关紧要。两者的工作都很好,因为它们根据ListBox的选择更改文本。但是在IntBox类中,我不得不添加只允许使用整数的代码。为了做到这一点,我利用了IntBox类中的TextChanged事件。最终结果是:

using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
 namespace Herculese
{
public class IntBox : TextBoxDX
{
    //INIT PROPERTIES
    private int _MaxVal = 0;
    private int _MinVal = 0;
    private bool _AllowZeroValue = false;
    //INIT STRING TO KEEP TRACK OF TEXT BEFORE CHANGES
    private string originalText;
    public IntBox()
    {
        //ADD TO TEXTCHANGED HANDLER
        TextChanged += new TextChangedEventHandler(My_OnTextChanged);
        //STORE ORIGINAL TEXT
        originalText = this.Text;
    }
    //EVENT HANDLER WHEN TEXT IS CHANGED
    private void My_OnTextChanged(object sender, EventArgs e)
    {
        //IF THERE IS TEXT IN THE BOX,
        MessageBox.Show("yee");
        if (this.Text.Length > 0)
        {
            //REMOVE SPACES AND LEADING ZEROS FROM STRING
            if (!_AllowZeroValue)
                this.Text = this.Text.TrimStart('0');
            this.Text = Regex.Replace(this.Text, @"'s+", "");
            //IF VALUE ISN'T NUMERICAL OR NOTHING IS LEFT AFTER REMOVING ZEROS AND SPACES, CHANGE TEXT BACK TO ORIGINAL
            Regex regex = new Regex("[^0-9]+");
            if (regex.IsMatch(this.Text) || this.Text.Length < 1)
            {
                this.Text = originalText;
                System.Media.SystemSounds.Beep.Play();
            }
            //IF VALUE IS NUMERICAL,
            else
            {
                //MAKE SURE VALUE IS WITHIN ACCEPTED RANGE. IF NOT, CHANGE IT TO HIGHEST/LOWEST AVAILABLE RESPECTIVELY
                int intText;
                intText = Convert.ToInt32(this.Text);
                if (intText > _MaxVal)
                {
                    this.Text = _MaxVal.ToString();
                    System.Media.SystemSounds.Beep.Play();
                }
                else if (intText < _MinVal)
                {
                    this.Text = _MinVal.ToString();
                    System.Media.SystemSounds.Beep.Play();
                }
                //SUCCESS!  UPDATE ORIGINAL TEXT WITH NEW VALID VALUE.
                else originalText = this.Text;
            }
        }
    }
    //PROVIDE GET/SET PROPERTIES
    public int MaxVal
    {
        get { return _MaxVal; }
        set { _MaxVal = value; }
    }
    public int MinVal
    {
        get { return _MinVal; }
        set { _MinVal = value; }
    }
    public bool AllowZeroValue
    {
        get { return _AllowZeroValue; }
        set { _AllowZeroValue = value; }
    }
}
}

正如你所看到的,我在IntBoxTextChanged度过了一段美好的时光。狂野派对,你能想到的。突然我意识到IntBox的绑定已经不起作用了。我可以手动更改文本。它只接受整数,并且像符咒一样工作。但是更改ListBox的选择不再更新文本。如果我删除了My_OnTextChanged中的代码,则绑定再次工作。我想是我的代码造成了问题。所以我今天带着全新的头脑回来,意识到了一些奇怪的事情。

如果我删除My_OnTextChanged中的代码并将其替换为MessageBox,则绑定将工作,并显示消息框。这很有道理,并进一步表明我的代码导致了这个问题。现在,奇怪的是:如果我在MessageBox代码之后将代码放回事件中,绑定将再次断开,MessageBox永远不会显示,这意味着事件永远不会触发。我只能说…呼?!我已经重新制作了好几次,只是为了确保我没有疯。我唯一能想到的另一件事是与它继承的TextBoxDX发生冲突,所以我让它直接从TextBox继承,得到了相同的结果。。。有人知道这件事的线索吗?

我在TextChanged事件中的代码破坏了WPF中的绑定,并导致了非常奇怪的行为

您正在为Text分配一个新值,该值将删除原始绑定,因为您已将其替换为新字符串。

尝试使用base.SetCurrentValue(TextProperty, value); 而不是使用this.Text = "Somthing"

示例:

//IF VALUE ISN'T NUMERICAL OR NOTHING IS LEFT AFTER REMOVING ZEROS AND SPACES, CHANGE TEXT BACK TO ORIGINAL
Regex regex = new Regex("[^0-9]+");
if (regex.IsMatch(this.Text) || this.Text.Length < 1)
{
    // this.Text = originalText;
    base.SetCurrentValue(TextProperty, originalText);
    System.Media.SystemSounds.Beep.Play();
}

SetCurrentValue设置依赖属性的值,而不更改其值源。