【问题标题】:TextBox leave causes PropertyChanged get fired twiceTextBox leave 导致 PropertyChanged 被触发两次
【发布时间】:2013-12-25 19:08:45
【问题描述】:

TextBoxText 属性绑定到该对象实现INotifyPropertyChanged 的对象属性时,事件PropertyChanged 可能会触发两次,同时具有相同的值: 1) 当文本在TextBox 内改变时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"));
        }
    }
}

要重现问题,请在上方文本框中输入内容,检查控制台,然后输入下方文本框并再次检查控制台。离开时,报告财产变化。为什么?

【问题讨论】:

  • 边界正常。为什么要更新源两次?

标签: c# winforms binding


【解决方案1】:

Binding.DataSourceUpdateMode 属性的默认值为OnValidation。在此配置中,数据源仅在 Validating 事件发生时更新。在您的示例中,您使用 OnPropertyChanged 模式,因此您另外在文本框内的文本发生更改时请求更新数据源。

这是默认行为,即 Binding 类是以这种方式实现的。如果您想了解更多详细信息,可以使用反射器检查 Binding.Target_PropertyChangedBinding.Target_Validate 方法。

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

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

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

【讨论】:

    【解决方案2】:

    根据 Michal 的回答,我找到了关闭 TextBoxCausesValidation 属性的解决方案:

    textBox.CausesValidation = false;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-27
      • 2021-04-26
      相关资源
      最近更新 更多