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

Nor*_*ren 2 .net c# data-binding winforms

技术:.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));
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:更新的代码段.

sta*_*ica 6

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

你有没有设置:

form1BindingSource.DataSource = this;  // (or whatever the real data source is)
Run Code Online (Sandbox Code Playgroud)

例如在表单的构造函数中,之后InitializeComponent

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


一些进一步的细节建议:

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

  2. 正如@rfmodulator在他的回答中所说,BindableAttribute附属于该领域:

    [Bindable(true)]
    private String cursorPosition;
    public String CursorPosition
    …
    
    Run Code Online (Sandbox Code Playgroud)

    您可能想将它附加到该属性:

    private String cursorPosition;
    [Bindable(true)]
    public String CursorPosition
    …
    
    Run Code Online (Sandbox Code Playgroud)
  3. 你的二传手应该看起来像这样:

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

    也就是说,仅PropertyChanged在属性值实际更改时引发事件.

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

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

    这是因为理论上PropertyChanged可以null检查和调用之间进行更改.您可以通过创建事件委托的本地副本来排除这种理论上的可能性.

    PS:为了准确,因为杰弗里里希特指出了"通过C#CLR"他的书,一个局部变量还是不太够:理想情况下,你会分配Interlocked.CompareExchange(ref PropertyChanged, null, null)handler(而不是简单PropertyChanged),因为使用该方法将防止JIT代码发电机优化掉局部变量(IIRC).