C# PropertyChanged 事件-数据绑定
在.NET平台上,数据绑定是一项令人十分愉快的技术。利用数据绑定能减少代码,简化控制逻辑。
通常,可以将某个对象的一个属性绑定到一个可视化的控件上,当属性值改变时,控件上的显示数据也随之发生变化。要实现这一功能,只需要为自定义对象实现 INotifyPropertyChanged 接口即可。此接口中定义了 PropertyChanged 事件,我们只需在属性值改变时触发该事件即可。下面的例子说明如何绑定如何自定义可用于数据绑定的对象:
假设我们有自定义对象 CustomizedObject 和窗体上的 Label 控件 label1,想要将 CustomizedObject 的 Date 属性和 label1.Text 关联起来,Date 属性值会在程序运行过程当中发生变化(例如点击 Button 控件 button1),并且直接反映在 label1.Text 上。下面的代码可以实现上述功能:
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.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
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);
}
#region IDateChanged Members
public event DateChangedHandler DateChanged;
// 添加一个触发 DateChanged 事件的通用方法
protected virtual void DateChangedMethod(DateChangedEventArgs e)
{
if (DateChanged != null)
{
DateChanged(this, e);
}
}
#endregion
}
// 自定义对象 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)
{
if (PropertyChanged != null)
{
PropertyChanged(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; }
}
}