在.NET平台上,数据绑定是一项令人十分愉快的技术。利用数据绑定能减少代码,简化控制逻辑。

通常,可以将某个对象的一个属性绑定到一个可视化的控件上,当属性值改变时,控件上的显示数据也随之发生变化。要实现这一功能,只需要为自定义对象实现 INotifyPropertyChanged 接口即可。此接口中定义了 PropertyChanged 事件,我们只需在属性值改变时触发该事件即可。下面的例子说明如何绑定如何自定义可用于数据绑定的对象:

假设我们有自定义对象 CustomizedObject 和窗体上的 Label 控件 label1,想要将 CustomizedObject 的 Date 属性和 label1.Text 关联起来,Date 属性值会在程序运行过程当中发生变化(例如点击 Button 控件 button1),并且直接反映在 label1.Text 上。下面的代码可以实现上述功能:
这个例子是点击 按钮后 日期自动加1.

using System;

using System.ComponentModel;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        private CustomizedObject myObject;
 

        public Form1()

        {

            InitializeComponent();

 

            // 初始化CustomizedObject对象

            myObject = new CustomizedObject { Date = DateTime.Now };

 

            // 绑定对象的属性到label1

            label1.DataBindings.Add("Text", myObject, "Date");

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            // 点击按钮改变对象的属性值

            myObject.Date = myObject.Date.AddDays(1);

        }

 

    }

 

    // 自定义对象 CustomizedObject 并实现 INotifyPropertyChanged 接口

    public class CustomizedObject : INotifyPropertyChanged

    {

        private DateTime dateValue;
 

        // 自定义一个 Date 属性

        public DateTime Date

        {

            get { return dateValue; }

            set

            {

                dateValue = value;

                NotifyPropertyChanged("Date");

            }

        }

 

        #region INotifyPropertyChanged Members

 

        public event PropertyChangedEventHandler PropertyChanged;

 

        // 添加一个触发 PropertyChanged 事件的通用方法

        protected virtual void NotifyPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

         #endregion

    }

}

其实从上面的例子中可以学习到如何自定义事件,这在开发控件时十分有用且非常重要。通过观察 INotifyPropertyChanged 接口可以知道它内部有一个成员,那就是:

event PropertyChangedEventHandler PropertyChanged;

而其中的 PropertyChangedEventHandler 实质上是一个委托,明白了这一点就可以自定义事件了。

现在,开始为 Form1 自定义事件 DateChanged (事件一般是定义在控件或组件中的,这里只是为了说明其过程而没有重新定义一个控件),首先需要一个事件参数类型:

public class DateChangedEventArgs : EventArgs

{

    public DateTime OldValue { get; set; }

    public DateTime NewValue { get; set; }

}

声明一个事件处理委托

public delegate void DateChangedHandler(object sender,
DateChangedEventArgs e);

我们可以将事件直接添加到Form1的定义中,但有时为了代码的通用性,可以将事件封装到一个接口中,例如:

public interface IDateChanged

{

    event DateChangedHandler DateChanged;

}

然后我们为Form1实现 IDateChanged 接口,并在button1点击时触发该事件。以下是完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 事件处理propettychanged
{
    public partial class Form1 : Form, IDateChanged
    {
        private CustomizedObject myObject;
        public Form1()
        {
            InitializeComponent();
            // 初始化CustomizedObject对象
            myObject = new CustomizedObject { Date = DateTime.Now };
            // 绑定对象的属性到label1
            label1.DataBindings.Add("Text", myObject, "Date");
            // 添加 DateChanged 事件的处理逻辑
            this.DateChanged += new DateChangedHandler(Form1_DateChanged);
        }
        private void Form1_DateChanged(object sender, DateChangedEventArgs e)
        {
            string message = string.Format(
                "DateChanged event triggered!nOldValue: {0}nNew Value: {1}",
                e.OldValue,
                e.NewValue);
            MessageBox.Show(message);
        }



        private void button1_Click(object sender, EventArgs e)

        {
            // 点击按钮改变对象的属性值并触发 DateChanged 事件
            DateChangedEventArgs ev = new DateChangedEventArgs
            {
                OldValue = myObject.Date,
                NewValue = myObject.Date.AddDays(1)
            };
            myObject.Date = ev.NewValue;
            DateChangedMethod(ev);
        }


        public event DateChangedHandler DateChanged;

        // 添加一个触发 DateChanged 事件的通用方法

        protected virtual void DateChangedMethod(DateChangedEventArgs e)
        {
            if (DateChanged != null)
            {
                DateChanged(this, e);
            }
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }
    }



    // 自定义对象 CustomizedObject 并实现 INotifyPropertyChanged 和 IDateChanged 接口

    public class CustomizedObject : INotifyPropertyChanged
    {
        private DateTime dateValue;
        // 自定义一个 Date 属性
        public DateTime Date
        {
            get { return dateValue; }
            set
            {
                dateValue = value;
                NotifyPropertyChanged("Date");
            }
        }
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        // 添加一个触发 PropertyChanged 事件的通用方法
        protected virtual void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }



    // DateChanged 事件委托

    public delegate void DateChangedHandler(object sender, DateChangedEventArgs e);



    // 用于封装事件的接口

    public interface IDateChanged
    {
        event DateChangedHandler DateChanged;
    }



    // DateChanged 事件参数

    public class DateChangedEventArgs : EventArgs
    {
        public DateTime OldValue { get; set; }
        public DateTime NewValue { get; set; }
    }
}