最近做项目用到DataGridView,用它绑定数据源后,如果数据源中的数据修改无法及时刷新到控件上,必须切换单元格的焦点才能导致刷新显示新数值,通过查官方文档,用INotifyPropertyChanged解决此问题。
案例如下:
首先定义一个类:Customer
public class Customer { public string CustomerName { get; set; } public string PhoneNumber { get; set; } }
创建一个绑定数据集:
private BindingList<Customer> customers = new BindingList<Customer>();
向数据集中添加数据并绑定到控件:
customers.Add(new Customer() { CustomerName = "张三", PhoneNumber = "010-5263" }); customers.Add(new Customer() { CustomerName = "李四", PhoneNumber = "010-8823" }); dataGridView1.DataSource = customers;
修改数据源:
customers[0].CustomerName = "王五";
此时,dataGridView1中没有及时刷新显示新数据。因为数据修改时并没有通知到控件,为此让Customer实现INotifyPropertyChanged接口,该接口只包含一个事件,当属性值改变时,触发该事件,从而导致注册该事件的方法被执行,达到通知控件的目的。这是通过事件实现观察者模式。
Customer实现INotifyPropertyChanged接口:
public class Customer:INotifyPropertyChanged { private string _customerName; private string _phoneNumber; public string CustomerName { get { return _customerName; } set { if(_customerName!=value) { _customerName = value; PropertyChanged(this, new PropertyChangedEventArgs("CustomerName")); } } } public string PhoneNumber { get { return _phoneNumber; } set { if (_phoneNumber != value) { _phoneNumber = value; PropertyChanged(this, new PropertyChangedEventArgs("PhoneNumber")); } } } public event PropertyChangedEventHandler PropertyChanged = delegate { }; }
此时,再次执行修改数据源的代码,控件会及时刷新数据显示,因为属性值改变时通知了控件进行相应的处理。
如果在数据源中添加或删除一条数据,控件也会及时刷新显示,怎么回事?原来BindingList<T>实现了IBindingList接口,该接口声明了事件 ListChangedEventHandler,BindingList<T>在添加或删除记录时,触发该事件。显然,控件在绑定数据集(customers)时,订阅了该事件。