RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Tackle Complex Data Binding with Windows Forms 2.0

Two-way data binding can save you a ton of coding, as long as you can get the bound controls to behave the way you want them to.

sing the BindingSource and Binding objects in .NET 2.0, getting what you expect in minimal code becomes a whole lot easier. In this article, I will explore how to use the BindingSource and Binding objects to set up associations between complex data sources and bound controls. I'll show you how to keep multiple controls that are bound to the same data source synchronized, and how to control the formatting and parsing of the data in those controls.

The BindingSource and Binding classes encapsulate all the details of managing a data bound collection and keeping multiple controls that are bound to those objects synchronized.

One key capability of Windows Forms since the release of .NET 1.0 is two-way data binding. Data binding capabilities in Windows Forms involves support built into container controls (forms and user controls) as well as support built in to each data bound control itself. The collection and capabilities of data bound controls has increased in .NET 2.0. I will use some of those new features for the sample code in this article.

In the past, when you needed to manage multiple controls on a form that were bound to the same or related sets of data, it was easy to get dazed and confused because things were not designed as nicely as they could have been. You had to dive into low level forms of infrastructure, accessing binding contexts and currency managers in ways that were not at all intuitive.

In .NET 2.0, the data binding capabilities of forms and controls has been redesigned in a way that makes it much easier to keep complex data collections synchronized and formatted as desired. This article will build on the information presented by Steve Lasker in his articles on "Drag Once Databinding" in last year's September/October and November/December issues of Code Magazine. I'm going to focus more on the code you might write if you are wiring things up yourself to give you a deeper understanding of what the designers are doing for you when they write the code.

Note that the sample code for this article was developed using an early build of Beta 2. The names of some of the key components and properties have been refactored since Beta 1, including the DataConnector component being renamed to BindingSource.

Start with the Source
To do any data binding, you need a source of data. You can more easily bind to collections of custom objects in .NET 2.0, as was described by Lasker in his article. However, typed DataSets are still a very viable and powerful way of binding to data, and typed DataSets received some designer and code enhancements in .NET 2.0 as well. For this article, I will use a complex typed DataSet from the pubs sample database in SQL Server 2000.

The schema of the typed DataSet I'll be working with is shown in Figure 1. This is a slice of the data from the pubs database so that I can show a mix of one-to-many, many-to-one, and many-to-many data relationship combinations. The data is retrieved through a simple ADO.NET data access layer class contained in the download code. Figure 1 comes from the new typed DataSet designer in Visual Studio 2005.

Figure 1. PubsDataSet Schema: Here's the schema for the Pubs DataSet.
You can see that in addition to defining typed tables for each table in the DataSet, typed table adapters are also created. You can think of table adapters as typed data adapters that provide strongly typed methods for filling and updating the corresponding typed data table within a DataSet. The new designer also picks up on foreign key relations in the database when you drag and drop tables from Server Explorer onto the designer surface, and the corresponding data relations are added to the typed DataSet along with corresponding members in the tables that allow you to navigate to child or parent rows.

The GetPublicationData() method in the data access class simply uses each of the table adapters to fill the corresponding tables to give you some complex related data to work with.

   public static void 
     GetPublicationData(PubsDataSet data)
      authorsTableAdapter authorsAdapter = new 
      titlesTableAdapter titlesAdapter = new 
      titleauthorTableAdapter titleAuthorAdapter
         = new titleauthorTableAdapter();
      publishersTableAdapter publishersAdapter = 
   new publishersTableAdapter();

If you drag and drop data sources onto a form or onto controls from the Data Sources window, the designer will add controls and components to your form and will add lines of code to the Form.Load event handler to fill the DataSets. For real world applications, you will usually want to control this process yourself through a data access layer or methods like that shown above. You can still take advantage of the table adapters to act as your main data access components for each tabular set of data. You can create tables in typed DataSets based on the result set returned from stored procedures or views as well, so the data represented by a table in your DataSet does not have to be tightly coupled to the table schema of your database.

When you talk about data sources in the context of Windows Forms data binding, keep in mind that the data binding mechanisms are designed to be agnostic of the actual type of the collection of data, as well as the type of the individual data items in the collection. Also, in the context of data binding, data sources mean in-memory stores of data, as opposed to the actual data sources where the data came from, like a database or object persistence store. So while you might often deal with data sources that are typed DataSets where the collections are strongly typed data tables and the items are strongly typed data rows, you might just as often deal with custom collection classes containing custom business objects. When the collection is a data table, the data items are rows and the data members within a row are fields. For custom objects the items are the object instances and the data members are the public properties on those objects.

The data binding mechanisms of Windows Forms don't really care whether you are binding to DataSets or custom collections as long as the collection and object types implement a certain set of interfaces that indicate what their capabilities are with respect to data binding. The minimum requirement for a collection to be used with Windows Forms data binding is to implement the IList interface. Doing so allows items in the collection to be iterated over, displayed, and edited if desired. However, if the collection implements the IBindingList interface, it can support filtering and sorting as well.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date