在名为property的属性上进行数据绑定时,Windows窗体出现故障

本文关键字:定时 绑定 Windows 窗体 故障 数据 property 属性 | 更新日期: 2023-09-27 17:57:40

我在Windows窗体中尝试数据绑定,发现了一个无法解释的小故障。我把这个问题贴在这里,希望社区里有人能给出一个有意义的答案。

我试图想出一种巧妙的方法来绑定依赖于对其他值的操作的只读值,并在依赖值更改时自动更新它。

我创建了一个包含3个文本框的表单,希望前两个文本框之和出现在第三个文本框中。

以下代码应该可以工作,但不能,至少不能正常工作:

public class Model : INotifyPropertyChanged
{
    private int m_valueA;
    private int m_valueB;
    public int ValueA
    {
        get { return m_valueA; }
        set { m_valueA = value; RaisePropertyChanged("ValueA"); }
    }
    public int ValueB
    {
        get { return m_valueB; }
        set { m_valueB = value; RaisePropertyChanged("ValueB"); }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class DynamicBindingProperty<T> : INotifyPropertyChanged
{
    private Func<T> m_function;
    private HashSet<string> m_properties;
    public DynamicBindingProperty(Func<T> function, INotifyPropertyChanged container, IEnumerable<string> properties)
    {
        m_function = function;
        m_properties = new HashSet<string>(properties);
        container.PropertyChanged += DynamicBindingProperty_PropertyChanged;
    }
    public T Property { get { return m_function(); } }
    void DynamicBindingProperty_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (!m_properties.Contains(e.PropertyName)) return;
        if (PropertyChanged == null) return;
        PropertyChanged(this, new PropertyChangedEventArgs("Property"));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        InitializeDataBinding();
    }
    private void InitializeDataBinding()
    {
        Model model = new Model();
        DynamicBindingProperty<int> tmp = new DynamicBindingProperty<int>(() => model.ValueA + model.ValueB, model, new[] {"ValueA", "ValueB"});
        textBox1.DataBindings.Add("Text", model, "ValueA");
        textBox2.DataBindings.Add("Text", model, "ValueB");
        textBox3.DataBindings.Add("Text", tmp, "Property");
        tmp.PropertyChanged += (sender, args) => Console.WriteLine(args.PropertyName);
    }
}

经过一段时间的尝试,我尝试将DynamicBindingProperty<T>。属性转换为其他属性(例如DynamicProperty),并且一切都按预期进行。现在,我本以为将Model.ValueA重命名为Property会有所突破,但它没有,而且仍然完美地工作。

这是怎么回事?

在名为property的属性上进行数据绑定时,Windows窗体出现故障

我做了一些调试,看起来像是一个bug(或者我不知道"属性不能命名为property"的要求)。如果更换

PropertyChanged(this, new PropertyChangedEventArgs("Property"));

带有

PropertyChanged(this, new PropertyChangedEventArgs(null));

它仍然不起作用-null或空字符串意味着任何属性都可能已更改。这表明问题不在处理更改通知方面,而是绑定没有正确建立。

如果向DynamicBindingProperty<T>添加与Property相同的第二个属性Property2,并将其绑定到第四个文本框,则如果使用空字符串null"Property2"执行更改通知,两个文本框都将正确更新。如果使用"Property"执行更改通知,则两个文本框都将无法正确更新。这表明与Property的绑定没有完全断开,并且还表明更改通知在某种程度上断开了。

遗憾的是,我无法确定出问题的确切位置,但如果你投入足够的时间来研究优化的框架源代码,你可能会发现问题。当处理更改通知时,属性名称为Property的情况和属性名称为Property2的情况之间的最早区别是在内部类System.ComponentModel.ReflectPropertyDescriptor中的OnValueChanged()中。在一种情况下,基本实现被调用,而在另一种情况中,它被跳过——至少如果调试器没有欺骗我,但这在优化的代码中很难判断。