In .Net, there are two types of data bindings, one is called one-way data binding and the other is called two-way data binding. One-way data binding means that after you bind a data source to a control, any change made on the control will be reflected to the underlying data source. But if you change the underlying data source (via other means than through the control), the control will not capture the change and reflect it in UI. Two-way data binding complements this limit. In a two-way binding, any change on the control is automatically reflected on the underlying data source and any change on the underlying data source is automatically reflected on the control.
To impliment a one-way binding is very easy:
List<DemoClass> instances_ = new List<DemoClass>();
BindingSource bs_ = new BindingSource();
bs_.DataSource = instances_;
dgv.DataSource = bs_;
Above four lines create a one-way data binding. dgv is the DataGridView. Here we rely on its own mechanism to populate columns and fill the grid with the underly data source instances_.
The problem is, when you try to add a new instance of DemoClass to instances_, the change is not reflected on the grid. If you change a property value of an existing instance, the change is not reflected on the grid as well. Two works need to be done for these.
Firstly, DemoClass has to impliment INotifyPropertyChanged interface. Implimenting this interface will add a public delegate to the DemoClass. Don’t worry about the delegate, data binding ensures the delegate will be assigned by other classes necessary. The key is to call this delegate on every setter method of every published property:
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName){
if(PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Here, I create a private method calling the delegate so we save some redundant code. What I now need to do is to ensure every setting calls the private method, passing the property’s name to it:
private string property_;
public string Property{
set{
property_ = value;
NotifyPropertyChanged(“Property”);
}
}
OK. Now, if we programatically change the Property value of an instance in instances_ list, the change will be immediately reflected to the grid.
How about adding and removing items from instances_? Unfortunately, we cannot let our List<DemoClass> to impliment INotifyPropertyChanged interface. A good news is, there is another class for this purpos, that is, BindingList<T>. BindingList<T> can be used exactly the same as List<T>. The difference is that BindingList<T> supports two-way binding. If we simply change the type of instances_ from List<DemoClass> to BindingList<DemoClass>, the adding and removing DemoClass changes will immediately reflect to the UI. And until now, we implement a two-way binding.
Until next time, happy coding!