HomeDigital EditionSearch Dotnet Cd
ASP.NET C# Certification Exams The CLI Data Access Editorials Extending .NET Fundamentals Interoperability Interviews Migrate Mobile .NET Mono .NET Interface Object-Oriented Programming Open Source Optimization Product/Book Reviews Security Source Code UML Visual Studio .NET

By now you have been playing around with the .NET Framework and in many cases actually building applications. You have been introduced to ASP.NET, Web services, and Windows Forms, and you've seen ADO.NET in action. ASP.NET has certainly shown you that utilizing data binding is not only an option but in many cases the absolute best way to fill controls with information. The same can be said for Windows Forms applications where you have seen how to bind controls to ADO.NET objects such as the DataView and the DataTable. You may have even have seen how you can bind controls to simple arrays and lists of information. In this article I'll take it up a notch and show you not only how you can bind controls to ADO.NET objects and arrays, but how the power of the .NET Framework also allows you to bind your classes to controls.

For many years, data binding was shunned by developers and architects for a number of reasons. For one, data binding was thought to cause scalability problems because the binding required live database connections. Until disconnected data was able to be bound in ADO, live database connections limited the usefulness of data binding. Second, because one of their goals is to shield the user interface from the structure of the database, architects avoided the use of data binding since it caused the user interface to be tightly bound to the database structure. Because of these past issues, many developers and architects still shun data binding (although it is extremely difficult to take advantage of ASP.NET features without using data binding). This article shows that these issues are no longer valid and, in fact, shows how ignoring data binding will result in wasted time when building your applications because of the development time that data binding can save.

This article concentrates on binding classes to Windows Forms controls because that is where most of the innovation with data binding has occurred. ASP.NET does not provide this functionality. I will discuss how to data-bind your classes to Windows Forms controls and I will show you how to build a collection of classes that can be data-bound to Windows Forms controls, including DataGrids. I will also show you some interesting ways that you can manage the controls that visually represent your class's properties.

Simple Binding of Classes to Controls
The most tedious part of building a rich-client application with VB using an object-oriented approach was the glue code that you needed to write to move data from controls that represented properties to the class properties and vice versa. You had to handle control-change or lost-focus events; you often had to handle exceptions thrown by the object property procedures (Errors in pre-VB.NET days) because of data validation. What if some code in a form changed the value of a property? What if some code in a class changed the value of a property?

These few items are just a couple of the issues you don't need to worry about when you data-bind your class to your control. Listing 1 shows an Employee class and how to data-bind a property of the class to a TextBox (all of the code for this article is available for download from below). When you execute the sample code, things appear to work well, until you change the class property value with code rather than changing the value of the TextBox. What happens ­ or actually, what doesn't happen ­ is that the TextBox text will not change to the new value in the class property. To accomplish this you need to add events for the properties that can change. Listing 2 shows the same class with the events required to cause changes to class properties from code rather than user interaction to be reflected back to the controls bound to the properties.

Now let's take a step back and look at the objects that are involved with the code in Listings 1 and 2 from both a direct and an indirect perspective. First let's look at the System.Windows.Forms.Binding (Binding) type. An instance of this type is created by the Control.Databindings.Add method or it can be created in code and then added to the Control.Databindings Collection. The key properties of the Binding type are summarized in Table 1.

Table 1

In addition to the properties mentioned previously, there are two other members of the Binding type that are of interest: Format and Parse events. The Format and Parse events allow you to translate information contained in the class into a format the control can handle and then again format the information back into the class property. Listing 3 uses the Format event to add currency symbols to the value of the Salary property and to remove the currency symbols when the value in the control is changed.

The information within a class property may not be of the proper type for the property of the control to which you are binding it. The Format and Parse events of the Binding object allow you to control the conversion when data is moving from the class property to the control property and vice versa (see Listing 3).

Digging deeper, we discover that every form automatically has an instance of the System.Windows.Forms.BindingContext (BindingContext) type, which is available through the Form.BindingContext property. The BindingContext is a collection of System.Windows.Forms.BindingManagerBase (BindingManagerBase) types that contains an item for every data source (e.g., ADO.NET DataTable, ArrayList, Custom Object) used in data binding on the form. In the next section I will show you how to use the BindingManageBase type to provide for navigation of collections of objects that are data-bound to controls.

Complex Data Binding of Collections to Controls
When I design user interfaces I generally use 90% simple data binding, but in some cases I need to bind a collection of objects to controls rather than just one instance of a class. The .NET Framework supports this option as well. To do this we need to understand the use of interfaces defined in the .NET Framework.

There are a number of interfaces involved with data binding, the most important being the System.ComponentModel.IBindingList. If you create an object that you want to be bindable to a grid or to support data-binding a list to controls such as TextBoxes or CheckBoxes, you will need to implement this interface. Listing 4 shows an abstract class called BindableCollection and an Employees class that inherits from the BindableCollection abstract class. The IBindingList interface is large, but in most cases the implementation is simple (and can be abstracted away so you inherit from a class that does the implementation, as is the case with my example).

The key to the implementation is the raising of events when an item in the collections is modified in any way. This is accomplished via the OnClear, OnSet, OnInsert, and OnRemove event handlers for the collection and also via a method, CollectionItemChanged, that is callable by items that are added to the collection.

To operate correctly, the items in the collection need to call the collection's CollectionItemChanged method whenever the values change. The CollectionItemChanged event will notify controls that are data-bound to the collection. Now you can data-bind a collection to a DataGrid or simple controls, as shown in Listing 5. The code in Listing 5 is fairly simple and illustrates how the key to binding is the construction of the class. To the developer using the class in the user interface, it is just another type.

Creating the BindableCollection abstract class simplifies the creation of collections that implement the IBindingList interface. Listing 4 shows my sample BindableCollection abstract class and the Employees class that inherits from it.

Binding to a Collection
Binding data to a grid requires the class to implement IBindingList, but the code to data-bind the class to the grid or simple controls is simple (see Listing 5).

Navigating Through Complex Data-Bound Classes
Now that we have created a complex data-bound class and have data-bound an instance to a control, you may be wondering how to navigate through the individual items. This brings us back to the BindingManagerBase type. The BindingManagerBase type has a number of methods to facilitate navigation through classes that implement IBindingList. First, the BindingManagerBase is an abstract type and two types in the .NET Framework inherit from it. The two types are the System.Windows.Forms.CurrencyManager (CurrencyManager) type and the System.Windows.Forms.PropertyManager (PropertyManager) type.

The runtime will create one of these two types based on what you data-bind to. The PropertyManager type is created when you data-bind to a simple type (such as a single object) and the CurrencyManager is used when you data-bind to a complex type (a type that implements IBindingList). When our Employees collection class in Listing 4 is bound to controls, a CurrencyManager type is created and added to the BindingContext collection. The CurrencyManager type has the methods described in Table 2, which are used for navigation.

Table 2

Navigation becomes an exercise in manipulating the CurrencyManager. Listing 6 manipulates the CurrencyManager with the common navigation that developers provide for user interfaces. When changing the value of a property with standard types, the standard object.property syntax is used.

You've learned how to data-bind simple and complex classes to a variety of controls. Now let's take a step back and look at what properties of controls we can data-bind and then let's take a second look at the capabilities of the Binding type.

Controlling the User Interface Through Data Binding
Typically, developers look at data binding as a way to fill controls with values that users manipulate. This is not the only possible use. For instance, a data-entry form may take in information for an employee in my example. Typically, a class like an employee will have an IsValid flag or an IsDirty flag. With data binding we can control the ability to click the Save button on a form by binding the Enabled property of the button to the IsValid property of the employee. So now, as properties of the employee are manipulated, the IsValid property of the employee will be set to the proper setting and as soon as the employee is valid, the Save button will enable. This is in contrast to how developers use timers to enable the Save button by periodically checking the IsValid property and enabling or disabling the button in the Timer event. This is just one example of when you might data-bind to a control for which you typically wouldn't use data binding. Data binding is extremely powerful when you extend your thinking to properties and controls that you hadn't thought about before. In some of the work my company is doing, we utilize data binding to bind to many properties of a control. For instance, we use data binding on TextBoxes to control the properties in Table 3.

Table 3

The key to this is adding additional information to each of your properties in a business class. After all, you want to indicate the information for each business class property. For instance, for the employee class we want to have this additional information for all of the properties. Then in the implementation of the class, we will manipulate the additional information based on a number of criteria such as validation, security, and object state. So the key question now is how to add the additional details to each of the properties. I have explored two methods of doing this. The first is the method I used with VB6 and its style of data binding, which involved an internal collection of Attribute objects that contained one item for each property. The other method was to explore inheritance and containment to create richer types to be used as the types exposed by the properties.

So the goal was to create a richer string type, integer type, datetime type, etc. The problem was that the string, integer, and datetime types are all sealed and cannot be inherited from. So that meant we had to resort to containment to extend the types. The only problem with this is that now the value of the FirstName property, for instance, of the employee type had to be manipulated using code similar to that in Listing 6 rather than the code in Listing 7. We created a base type called BindingType and then inherited from that to create BindingString, BindingInteger, BindingBoolean, etc. These new types have the additional properties shown in Table 4.

Table 4

This leads us into an exploration of the third parameter in the constructor for a Binding type. The DataMember parameter is quite often thought to be just the name of the property that you are data-binding, but it actually consists of a path and a property. So for our employee class, a possible DataMember value would be "FirstName.Text" or "FirstName.BackColor". In these examples, "FirstName" is the path and "Text" or "BackColor" is the property.

Conclusion
In the samples available for download, I have included a few different ways that you can utilize data binding in an application. Applications that are built in this manner are easily data driven and adaptable to user change without code changes and redeployments. Take what you have learned in this article and explore the .NET Framework. You will discover that the data-binding capabilities are incredible and extendible. Explore how you can create components that can be bound at design time, and explore different methods of using data to manipulate your applications.

About The Author
Keith Franklin is one of the founders and leading forces behind Chicago's premier .NET development services company, Empowered Software Solutions. In addition to acting as chief software architect for Empowered, Keith directs the Chicago.NET Users Group (CNUG) and is a founding board member of the International .NET Association (INETA) and .NET Developer's Journal. He has authored many articles on .NET technologies and has written the book VB.NET for Developers from Sams Publishing. ka_franklin@empowered.com

Source Code: zip file format ~4.20 KB

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.

  E-mail: info@sys-con.com