简单绑定的.NET数据绑定无法正常工作

时间:2012-02-22 20:47:54

标签: c# .net winforms data-binding

技术:.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。我错过了什么?

修改:更新了代码段。

4 个答案:

答案 0 :(得分:6)

  

从设计器开始,我设置了标签的Data Binding,将Text属性绑定到form1BindingSource - CursorPosition。我错过了什么?

你有没有设置:

form1BindingSource.DataSource = this;  // (or whatever the real data source is)

e.g。在InitializeComponent之后的表单构造函数中?

(这假设您的Form1实例是数据源,并且您通过BindingSource将控件绑定到它。)


一些进一步的详细建议:

  1. 选择表单本身作为数据源有点不寻常。恕我直言,最好将所有绑定属性分离为单独的非UI数据对象。然后,您可以为INotifyPropertyChanged实现创建可重用的基本类型。

  2. 正如@rfmodulator在答案中所说, BindableAttribute 附在该字段上:

    [Bindable(true)]
    private String cursorPosition;
    public String CursorPosition
    …
    

    你可能想把它附在财产上:

    private String cursorPosition;
    [Bindable(true)]
    public String CursorPosition
    …
    
  3. 您的 setter 应该如下所示:

    set
    {
        if (!string.Equals(cursorPosition, value)      // +
        {                                              // +
            cursorPosition = value;
            NotifyPropertyChanged("CursorPosition");
        }                                              // +
    }
    

    也就是说,只有在属性值实际发生变化时才会引发PropertyChanged事件。

  4. 您可能希望将 NotifyPropertyChanged方法更改为:

    private void NotifyPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;          // +
        if (handler != null)                                            // ~
        {
            handler(this, new PropertyChangedEventArgs(propertyName));  // ~
        }
    }
    

    这是因为PropertyChanged理论上 null检查和调用之间发生了变化。您可以通过创建事件委托的本地副本来排除这种理论上的可能性。

    PS:准确地说,正如Jeffrey Richter在他的书“通过C#CLR”中指出的那样,局部变量仍然不够:理想情况下,你将Interlocked.CompareExchange(ref PropertyChanged, null, null)分配给{{1 (而不仅仅是handler)因为使用该方法将阻止JIT代码生成器优化掉局部变量(IIRC)。

答案 1 :(得分:2)

我假设您想要触发PropertyChanged事件?您在Mouse_Move中设置了支持变量的值,而不是属性的值。因此,不会调用对NotifyPropertyChanged的调用。

答案 2 :(得分:1)

您不应在componentscontrolsforms上实施INotifyPropertyChanged,因为数据绑定将依赖于XXXChanged事件范例来侦听更改通知。在内部,数据绑定使用property descriptors来监听变更事件。它们暗示了类如何检测PropertyDescriptor.SupportsChangeEvents property文档中的更改。这与winforms数据绑定的历史有关。 XXXChanged是做数据绑定的方法。在.NET 2.0之前更改通知。 INotifyPropertyChanged在2.0中引入,支持XXXChanged模式。

  

SupportsChangeEvents属性指示此属性的值更改通知是否可能来自属性描述符之外,例如来自组件本身,或者通知是否仅来自对SetValue方法的直接调用。例如,组件可能实现INotifyPropertyChanged接口,或者可能具有此属性的显式nameChanged事件。

答案 3 :(得分:1)

您在字段上设置Bindable属性,但以属性作为参数调用NotifyPropertyChanged