The CurrencyManager manages a collection of bindings between list controls and a data source object. It exposes ad hoc members to let controls retrieve the currently selected item (the Current
property), get and set the position of the current item, and be notified of position or current item changes via the PositionChanged
events. Table 1
lists the properties of the class.
Table 1: Properties supported by the CurrencyManager class.
Returns the collection of bindings.
Returns the number of rows in the data source managed by the class.
Contains the value of the current item in the data source. To use the value of the current item you must cast the value returned by this property to the proper type.
Returns the list of data objects managed by the class. The property is an IList type and must be cast to the specific data source list type.
A zero-based index that specifies a position in the underlying list.
The CurrencyManager class standardizes the access to the variety of enumerable lists you can use in .NET data-bound applications. Whenever a list control (such as a ComboBox) changes its selected item because the user clicks on a row, the Current
properties on the associated binding manager object are updated. When this happens two events fire: CurrentChanged
Both events are served by an EventHandler
delegate object and don't carry specific information to the caller. Both events are notifications that something happened in the data source. All controls designed to work in master/details scenarios can hook up these two events and automatically refresh. This is the underlying mechanism that explains the otherwise weird phenomenon of two ComboBoxes working unexpectedly (and in a manner not required to some extent) in sync.
In light of this information, let's briefly review the internal steps that bring one ComboBox in a form to update its selection whenever another similar control, bound to the same data source, changes its own selection.
Suppose you have two ComboBox controls in a Windows Forms and you bind both to the same data source objectsay, a DataSet. When the DataSource
property of the first ComboBox is set, a new entry is created in the BindingContext
collection of the form to link together a new instance of the CurrencyManager class and the data source. At the same time, the Bindings
collection of the CurrencyManager adds a reference to the ComboBox control.
When the second ComboBox is bound to the data source, the just-created binding manager is retrieved from the form's context and its Bindings
collection is updated to take the second ComboBox into account.
After initialization each ComboBox control also adds a handler for the CurrentChanged
event on the binding manager. The control retrieves its binding manager using the following code:
// m_dataSource is the internal member
// storing the data source object
cm = BindingContext[m_dataSource];
The following pseudo-code shows how the control defines its event handler for the CurrentChanged
event handler in the preceding code is a ComboBox internal function called to react to the change of selection that takes place in any control in the context bound to the same data source.
Because of the way the event handlers are attached to a ComboBox when a new item is selected (either at startup or after a user's action), the Current and Position properties on the binding manager update to reflect the change. Then the binding manager fires the related events, namely the CurrentChanged
events. All controls in the binding context that subscribed to these events automatically receive the notification.
Now imagine you have a form with two ComboBox controls bound to the same data source. When one control changes the selected item, the other receives a notification from the currency manager and invokes its own selection-change event handler. In the case of ComboBox controls, the selection handler simply selects the same element that is current on the data source. The following pseudo-code illustrates the point.
void SelectionChanged(object sender,
if (bindingManager == null)
// Position points to the index of the newly
// selected item
this.SelectedIndex = bindingManager.Position;
If you love decompilers and you want to see the real source code of this feature, then locate the DataManager_ItemChanged
method in the ListControl class in the System.Windows.Forms namespace. ListControl is the base class of ComboBox.
How each control reacts to selection-change style events depends on the characteristics and behavior of the control itself. For example, the DataGrid control may raise an event when a row is changed, whereas a Drop-Down ListBox will raise an event when the user selects a new item. I'll return to this point shortly with an example. Meanwhile, let's look at the other, simpler, type of binding manager class.