TextBox leave causes PropertyChanged get fired twice

家住魔仙堡 提交于 2019-12-12 06:48:02

问题


When the Text property of a TextBox is bound to an object property which that object implements INotifyPropertyChanged, the event PropertyChanged may fire two times while having the same value: 1) when the text is changed inside the TextBox 2) when the control is leaving from it.

Consider these methods of a form:

    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");
    }

and the back-end class:

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"));
        }
    }
}

To reproduce the problem, type something in the upper textbox, check the console, and then enter the lower textbox and check again the console. Upon leaving, a property change is reported. Why?


回答1:


The default value of Binding.DataSourceUpdateMode property is OnValidation. In this configuration the data source is being only updated when Validating event occurs. In your example you use OnPropertyChanged mode, so you additionally request update of the data source whenever the text is changed inside the TextBox.

It is the default behaviour i.e. the Binding class was implemented in this way. If you want more details, you can examine Binding.Target_PropertyChanged and Binding.Target_Validate methods with a reflector.

From my perspective this behaviour isn't a problem but you need to change the implementation of the setter in the following way:

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

Even if we assume that the implementation of Binding class is wrong, I think that it is a good practise to check whether a value has changed before generating PropertyChanged event.




回答2:


Based on Michal's answer, I found the solution in switching off the CausesValidation property of TextBox as:

textBox.CausesValidation = false;


来源:https://stackoverflow.com/questions/20457670/textbox-leave-causes-propertychanged-get-fired-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!