我在Windows窗体中试验数据绑定,发现了一个我无法解释的故障。我在这里发布这个问题,希望社区中的某个人能够提出一个有意义的答案。
我尝试了一种巧妙的方法来绑定依赖于对其他值的操作的只读值,并在依赖值更改时自动更新它。
我创建了一个包含3个文本框的表单,我希望前2个的总和出现在第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&lt; T&gt; .Property重命名为其他东西(例如DynamicProperty),一切按预期工作!。现在,我期望通过将Model.ValueA重命名为Property来打破某些东西,但它没有,并且仍然完美无缺。
这里发生了什么?
答案 0 :(得分:2)
我做了一些调试,它看起来像一个bug(或要求“该属性不能被命名为Property”我不知道)。如果你替换
PropertyChanged(this, new PropertyChangedEventArgs("Property"));
带
PropertyChanged(this, new PropertyChangedEventArgs(null));
它仍然不起作用 - null
或空字符串表示任何属性可能已更改。这表明问题不在于处理更改通知,而是未正确建立绑定。
如果您将第二个属性Property2
添加到DynamicBindingProperty<T>
并与Property
相同并将其绑定到第四个文本框,那么两个文本框如果您使用空字符串null
或"Property2"
执行更改通知,则会正确更新。如果您使用"Property"
执行更改通知,文本框将不正确更新。这表明对Property
的绑定没有完全破坏,并且更改通知也有些破坏。
可悲的是,我无法确定出错的确切位置,但如果你投入足够的时间逐步完成优化的框架源代码,你可能会想出来。属性名称为Property
的案例与属性名称为Property2
的案例之间的最早差异我可以确定何时处理更改通知位于内部类OnValueChanged()
的{{1}}中。在一种情况下,在另一种情况下跳过基础实现被调用 - 至少如果调试器没有欺骗我,但在优化代码中很难说明。