Binding Windows.Forms Controls to Indexed Object Properties in VB.NET
Outlines a class that allows binding of form controls to properties with indexers in VB.NET
Introduction
One of the redeeming features of VB.NET -- and VB before it -- is the ease with which it is possible to create indexed properties. This means that you can write code of the form...
value = Object.Value(variable)
and
Object.Value(variable) = value
...rather than having to write code such as:
select case variable
case 0
value = Object.ValuXe
case 1
value = Object.ValueY
:
case n
end select
This can enormously simplify code that uses the object, and with simplicity (usually) comes reliability. There is a drawback, though. It isn't possible to bind form controls directly to indexed properties. So complexity creeps back into a product in the form of the code required to pass values from object to control and back again, as well as in the logic required to make sure that the packing and unpacking is carried out at the right time.
This article details a very simple little class, BindingMap
, that allows the binding of a control to an indexed property and, one hopes, takes us back towards simpler client code. The BindingMap
class has a single constructor and a single unindexed property, MapValue
. It is this property that is bound to the control. The BindingMap
object takes care to ensure that the correct property value of the object that we really want bound is made available/set by the MapValue
property. The BindingMap
object is instantiated with the target object, its property name and the index value to use. Note that you can only bind one control to one property signature at a time, but a control can be rebound to a different property signature as required.
Background
If you aren't familiar with object and control binding, have a quick look at the DataBinding
property of, say, the Forms textbox control.
Using the code
Creating a binding map is straightforward:
' First the identify which indexed value of the
' property you want to map to your control.
dim m as BindingMap = _
new BindingMap(MyObject, "PropertyName", PropertyIndex)
' Now point the control data binding at the binding map...
b = new Binding("Text", m, "MapValue")
control.DataBindings.Add(b)
The following excerpt from the sample project shows how it might be used in practice. The property Selectable
is indexed using an enumeration imaginatively named Index
.
' Instantiate our form level test object.
_test = new test
' First we have a standard binding to a run of the mill unindexed property...
dim b as Binding = new Binding("Text", _
_test, _
"Unadorned")
textboxA.DataBindings.Add(b)
' Now we bind an indexed property via our binding map.
b = new Binding("Text", _
new BindingMap(_test, "Selectable", test.Index.Kappa), _
"MapValue")
textboxK.DataBindings.Add(b)
'... and another to the 'b' index of the test::Selectable property
b = new Binding("Text", _
new BindingMap(_test, "Selectable", test.Index.Beta), _
"MapValue")
textboxB.DataBindings.Add(b)
If we wanted a single control to represent the contents of an indexed property and the selected property to vary according to user input, then we might write our binding code as follows:
sub Rebind(index as Object)
textbox.DataBindings.Clear
dim b as Binding = new Binding("Text", _
new BindingMap(_test, "Selectable", index), _
"MapValue")
textbox.DataBindings.Add(b)
end sub
Then call the Rebind
method as and when necessary.
Points of interest
Well, none really. It's just a straightforward solution to an irritating little coding problem.
History
- 2007.06.16 - First cut