A common and practical application ”binding properties to controls ”uses Reflection behind the scenes. This works in Windows Forms and Web pages.
DataBinding.sln contains an example of user -defined type Customer and a place to store customers as well as a Contacts class that can contain an ArrayList of contacts. The ArrayList implements an interface called IList , which supports enumeration that allows us to bind controls directly to our objects. The sample application is shown in Figure 4.1.
Figure 4.1. A simple form bound directly to the shown TextBox controls by using Reflection and DataBindings .
The Customer class contains two properties, Name and WebSite (as shown in the figure). The Contacts class contains an ArrayList field and a ReadOnly ArrayList property named Items . Here is the implementation of the Contacts.Items property.
Public ReadOnly Property Items() As ArrayList Get If (FItems Is Nothing) Then FItems = New ArrayList() Return FItems End Get End Property
The property uses the ReadOnly modifier, which means we can and will implement only a property getter. We will bind to the Contacts.Items property.
To bind one of the TextBox controls to a specific property of our customer ”aside from adding customers to a Contacts object ”we need to determine which property of the TextBox we are binding to and which property of Customer we will get the data from. TextBox.Text is an appropriate property of the TextBox to bind to, and it is reasonable to bind the Customer.Name property to that. Here is the single line of code needed to accomplish this.
TextBox1.DataBindings.Add("Text", FContacts.Items, "Name")
Assuming we have an instance of Contacts named FContacts , we invoke the TextBox1.DataBindings.Add method. The first argument represents the TextBox property to bind to. The second argument is our data source; it's pretty cool that we can bind right to our Contacts.Items collection. The third property is the name of the field in the Contacts.Items data source that we want to get data from. Literally, now, TextBox1 is a data-bound control; it is bound to a Contacts object.
It is interesting to note that ArrayList does not have a property named Name . Name is discovered by Reflection against a single object in the ArrayList . We implicitly create a binding object by passing the necessary arguments to the overloaded Add method. (We can also manually construct a binding object and pass that to Add too.) Reflection is used to examine the type of the objects stored in the ArrayList and to bind to the elements of that type. In this instance the object is a Customer object.
To make navigation automatic, implement an event handler for the buttons and change the position of the BindingContext associated with a particular control. For example, to implement forward navigation, increment the Position property of the BindingManagerBase object. In the following statement, TextBox1.BindingContext.Item returns a BindingManagerBase object.
TextBox1.BindingContext.Item(FContacts.Items).Position += 1
Incrementing the Position property of the BindingManagerBase will safely navigate to the next element in the collection. If all the controls on a form are bound to the same data source, you need to change the position of only one to update all. Decrement the position to move backward. The BindingManagerBase will not allow you to increment or decrement outside of the range of elements.
One of the benefits of an object-oriented framework is generalization and reuse. By generalizing how controls are bound, we have greater flexibility with what we bind to. Of course, we can bind to an ADO.NET DataSet object, or we can bind directly to collections of objects as demonstrated.