C# 文本框离开导致PropertyChanged被解雇两次

C# 文本框离开导致PropertyChanged被解雇两次,c#,winforms,binding,C#,Winforms,Binding,当TextBox的Text属性绑定到该对象实现的对象属性INotifyPropertyChanged时,事件PropertyChanged可能会在具有相同值的情况下触发两次: 1)当控件离开文本框时,文本在文本框内发生更改2) 考虑以下形式的方法: private void Form1_Load(object sender, EventArgs e) { TextBox textBox = new TextBox(); TextBox second

TextBox
Text
属性绑定到该对象实现的对象属性
INotifyPropertyChanged
时,事件
PropertyChanged
可能会在具有相同值的情况下触发两次: 1)当控件离开
文本框时,文本在
文本框内发生更改
2)

考虑以下形式的方法:

    private void Form1_Load(object sender, EventArgs e)
    {
        TextBox textBox = new TextBox();
        TextBox secondTextBox = new TextBox();
        secondTextBox.Location = new Point(0, 100);

        this.Controls.Add(textBox);
        this.Controls.Add(secondTextBox);

        MyClass instance = new MyClass();
        instance.PropertyChanged += instance_PropertyChanged;

        textBox.DataBindings.Add("Text", instance, "Id", true, DataSourceUpdateMode.OnPropertyChanged);
    }

    private void instance_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine(e.PropertyName + " changed");
    }
以及后端类:

private class MyClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    int _id;
    public int Id
    {
        get
        {
            return _id;
        }
        set
        {
            _id = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Id"));
        }
    }
}
要重现此问题,请在上部文本框中键入内容,检查控制台,然后输入下部文本框并再次检查控制台。离开时,报告财产变更。为什么?

Binding.DataSourceUpdateMode属性的默认值是OnValidation。在此配置中,仅当发生验证事件时才更新数据源。在您的示例中,您使用OnPropertyChanged模式,因此每当文本框中的文本发生更改时,您会请求更新数据源

这是默认行为,即绑定类是以这种方式实现的。如果需要更多详细信息,可以使用反射器检查Binding.Target_PropertyChanged和Binding.Target_Validate方法

从我的角度来看,这种行为不是问题,但您需要通过以下方式更改setter的实现:

set
{
    if(_id != value)
    {
        _id = value;
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("Id"));
    }
}

即使我们假设Binding类的实现是错误的,我认为在生成PropertyChanged事件之前检查值是否已更改是一种很好的做法。

根据Michal的回答,我找到了关闭
文本框的
CausesValidation
属性的解决方案,如下所示:

textBox.CausesValidation = false;

边界是可以的。为什么要两次更新源?