技术:.NET 4,C#,WinForms,Visual Studio 2010
我正在处理学习数据绑定,甚至无法得到一个简单的例子来按预期工作。我有一个带有我绑定标签的表单,显示当前鼠标光标坐标。
public partial class Form1 : Form, INotifyPropertyChanged
{
[Bindable(true)]
private String cursorPosition;
public String CursorPosition
{
get
{
return cursorPosition;
}
set
{
cursorPosition = value;
NotifyPropertyChanged("CursorPosition");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public Form1()
{
InitializeComponent();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
CursorPosition = "(" + Convert.ToString(e.X) + " , " + Convert.ToString(e.Y) + ")";
}
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
从设计器开始,我设置了标签的Data Binding,将Text属性绑定到form1BindingSource - CursorPosition。我错过了什么?
修改:更新了代码段。
答案 0 :(得分:6)
从设计器开始,我设置了标签的Data Binding,将Text属性绑定到form1BindingSource - CursorPosition。我错过了什么?
你有没有设置:
form1BindingSource.DataSource = this; // (or whatever the real data source is)
e.g。在InitializeComponent
之后的表单构造函数中?
(这假设您的Form1
实例是数据源,并且您通过BindingSource
将控件绑定到它。)
一些进一步的详细建议:
选择表单本身作为数据源有点不寻常。恕我直言,最好将所有绑定属性分离为单独的非UI数据对象。然后,您可以为INotifyPropertyChanged
实现创建可重用的基本类型。
正如@rfmodulator在答案中所说, BindableAttribute
附在该字段上:
[Bindable(true)]
private String cursorPosition;
public String CursorPosition
…
你可能想把它附在财产上:
private String cursorPosition;
[Bindable(true)]
public String CursorPosition
…
您的 setter 应该如下所示:
set
{
if (!string.Equals(cursorPosition, value) // +
{ // +
cursorPosition = value;
NotifyPropertyChanged("CursorPosition");
} // +
}
也就是说,只有在属性值实际发生变化时才会引发PropertyChanged
事件。
您可能希望将 NotifyPropertyChanged
方法更改为:
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged; // +
if (handler != null) // ~
{
handler(this, new PropertyChangedEventArgs(propertyName)); // ~
}
}
这是因为PropertyChanged
理论上 在null
检查和调用之间发生了变化。您可以通过创建事件委托的本地副本来排除这种理论上的可能性。
Interlocked.CompareExchange(ref PropertyChanged, null, null)
分配给{{1 (而不仅仅是handler
)因为使用该方法将阻止JIT代码生成器优化掉局部变量(IIRC)。 答案 1 :(得分:2)
我假设您想要触发PropertyChanged事件?您在Mouse_Move中设置了支持变量的值,而不是属性的值。因此,不会调用对NotifyPropertyChanged的调用。
答案 2 :(得分:1)
您不应在components,controls和forms上实施INotifyPropertyChanged,因为数据绑定将依赖于XXXChanged事件范例来侦听更改通知。在内部,数据绑定使用property descriptors来监听变更事件。它们暗示了类如何检测PropertyDescriptor.SupportsChangeEvents property文档中的更改。这与winforms数据绑定的历史有关。 XXXChanged是做数据绑定的方法。在.NET 2.0之前更改通知。 INotifyPropertyChanged在2.0中引入,支持XXXChanged模式。
SupportsChangeEvents属性指示此属性的值更改通知是否可能来自属性描述符之外,例如来自组件本身,或者通知是否仅来自对SetValue方法的直接调用。例如,组件可能实现INotifyPropertyChanged接口,或者可能具有此属性的显式nameChanged事件。
答案 3 :(得分:1)
您在字段上设置Bindable
属性,但以属性作为参数调用NotifyPropertyChanged
。