在名为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会有所突破,但它没有,而且仍然完美地工作。
这是怎么回事?
我做了一些调试,看起来像是一个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()
中。在一种情况下,基本实现被调用,而在另一种情况中,它被跳过——至少如果调试器没有欺骗我,但这在优化的代码中很难判断。