The single most important concept to understand about Windows
Forms data binding is that it is driven off of change notification. What this
means is that Windows Forms will not update a user interface element (Control)
unless that data source notifies the Windows Forms data binding runtime that the
data has changed (by providing a notification event). In the case of simple
property to property binding, the data source needs to provide property change
notification by either providing a "PropertyName"Changed event for the property
or by implementing the INotifyPropertyChanged interface. The
INotifyPropertyChanged interface is new in VS 2005 and can be used with
BindingList<T> to create bindable lists.
/*******************************************************************
* Setup (using the Visual Studio Form designer):
*
* Add a Label to the Form (label1)
* Add the following code to the Form.Load event
******************************************************************/
CurrentTime currentTime = new CurrentTime();
/*******************************************************************
* Bind Label.Text (string) to CurrentTime.Now
* Note: the Label will not update when "Now" changes because Now
* does not provide change notification.
******************************************************************/
Binding binding = new Binding("Text", currentTime, "Now", true);
binding.FormatString = "MM/dd/yyyy hh:MM:ss";
this.label1.DataBindings.Add(binding);
/***********************************************************************
* Setup (using the Visual Studio Form designer):
*
* Add a new class file to your project named "CurrentTime"
* Add the following code to the class implementation
**********************************************************************/
public class CurrentTime
{
System.Windows.Forms.Timer _timer;
public CurrentTime()
{
/***************************************************************
* Use a timer to keep track of the current timer
***************************************************************/
_timer = new System.Windows.Forms.Timer();
/***************************************************************
* Update the time every second
***************************************************************/
_timer.Interval = 1000;
_timer.Tick += delegate { this.Now = DateTime.Now; };
_timer.Start();
}
/*******************************************************************
* Use a timer to keep track of the current time
*******************************************************************/
private DateTime _now = DateTime.Now;
/*******************************************************************
* No Change Notification – bound controls will not update
*******************************************************************/
public DateTime Now
{
get { return _now; }
private set
{
if (_now != value)
{
_now = value;
}
}
}
}
/***********************************************************************
* Setup (using the Visual Studio Form designer):
*
* Use the Same Form as in the sample above but change the "CurrentTime"
* type to provide Change notification for the "Now" property. This sample
* uses the "Property"Changed pattern. The label Text value will correctly
* update in this sample.
***********************************************************************/
public class CurrentTime
{
System.Windows.Forms.Timer _timer;
public CurrentTime()
{
/***************************************************************
* Use a timer to keep track of the current timer
***************************************************************/
_timer = new System.Windows.Forms.Timer();
/***************************************************************
* Update the time every second
***************************************************************/
_timer.Interval = 1000;
_timer.Tick += delegate { this.Now = DateTime.Now; };
_timer.Start();
}
/*******************************************************************
* Use a timer to keep track of the current time
*******************************************************************/
private DateTime _now = DateTime.Now;
/*******************************************************************
* Property Change Notification fired – bound UI elements will
* update when this property changed
*
* This uses the "Property"Changed pattern
*******************************************************************/
public DateTime Now
{
get { return _now; }
private set
{
if (_now != value)
{
_now = value;
OnNowChanged(EventArgs.Empty);
}
}
}
/*******************************************************************
* Provide a "Property"Changed event
*******************************************************************/
public event EventHandler NowChanged;
protected virtual void OnNowChanged(EventArgs e)
{
if (null != NowChanged)
{
NowChanged(this, e);
}
}
}
Sample: Simple Binding with INotifyPropertyChanged
Change Notification (VS 2005) (VS Project: PropertyChangeNotification)
/***********************************************************************
* Setup (using the Visual Studio Form designer):
*
* Use the Same Form as in the sample above but replace with this version
* of the CurrentTime Type.
*
* This sample implements System.ComponentModel.INotifyPropertyChanged.
* The label Text value will correctly update in this sample.
**********************************************************************/
using System.ComponentModel;
public class CurrentTime : INotifyPropertyChanged
{
System.Windows.Forms.Timer _timer;
public CurrentTime()
{
/***************************************************************
* Use a timer to keep track of the current timer
***************************************************************/
_timer = new System.Windows.Forms.Timer();
/***************************************************************
* Update the time every second
***************************************************************/
_timer.Interval = 1000;
_timer.Tick += delegate { this.Now = DateTime.Now; };
_timer.Start();
}
/*******************************************************************
* Use a timer to keep track of the current time
*******************************************************************/
private DateTime _now = DateTime.Now;
/*******************************************************************
* Property Change Notification fired – bound UI elements will
* update when this property changed
*
* This uses INotifyPropertyChanged
*******************************************************************/
public DateTime Now
{
get { return _now; }
private set
{
if (_now != value)
{
_now = value;
OnPropertyChanged("Now");
}
}
}
/*******************************************************************
* Provide the INotifyPropertyChanged.PropertyChanged event
*******************************************************************/
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (null != PropertyChanged)
{
PropertyChanged(this, e);
}
}
}
List Change Notification
Sample: BindingList with INotifyPropertyChanged Change
Notification (VS 2005) (VS Project: BindingListNotification (INPC))
Sample: BindingList without INotifyPropertyChanged Change
Notification (VS 2005) (VS Project: BindingListNotification (no INPC))
Sample: ListChangeNotification
When the data source is a list (complex or simple bound
list), the data source needs to provide both list and property change notification
via the IBindingList interface. List change notification is used to
notify user interface elements when an item has been added, removed or deleted
from the list. Property change notification on a list is used to notify user
interface elements that a property on an item in the list has changed (e.g. the
"Name" property on Customer instance in the nth position of
the list changed). One key aspect of list binding in Windows Forms is that
IBindingList provides both list based change notification and property based
change notification. In other words, and this is a key point, Windows Forms
controls that are bound to a list will not listen to property change
notification provided by items within the list – rather Windows Forms requires
the list to provide this notification on behalf of the contained items.
Prior to VS 2005, implementing IBindingList required a tight
coupling between the list and contained list items as the contained items
needed to tell the list when properties on them changed. In VS 2005, this has
been simplified with the introduction of BindingList<T> and the
INotifyPropertyChanged interface. BindingList<T> is a generic
implementation of the IBindingList interface that will automatically translate
child INotifyPropertyChanged events into IBindingList.ListChanged events.
Note that the experience of binding to a list based data
source that is not an IBindingList may be improved if the list is bound through
a BindingSource.