|
|
|
|
Data binding in Windows Forms 2.0
By
John Charles Olamendy December 02, 2008
This article is intented to illustrate the principles of data binding in .NET Windows Forms 2.0 as well as a description of data set and data-bound controls. Data binding techniques are sometimes one of the most important part of many enterprise applications and a lot of developers don’t understand at all. Data binding is the mechanism for automatically associating and synchronizing data objects in memory with controls for presenting and gathering data from the user interface.
|
Author Rank:
|
|
Technologies:
.NET 2.0, Windows Forms,Visual C# .NET |
|
Total downloads : |
|
|
Total page views : |
7500 |
|
Rating : |
|
5/5 |
|
This article has been rated : |
2 times |
|
|
|
Similar ArticlesMost ReadTop RatedLatest
|
|
Related EbooksTop Videos
|
|
|
Description
|
|
The Complete Visual C# Programmer's Guide, written by the authors of C# Corner, covers most of the major components that make up C# and the .NETenvironment including Windows Forms, ADO.NET, GDI+, Web Services, and Security. The book is geared toward the beginner to intermediate programmers.
|
|
|
|
|
|
|
|
|
|
|
|
|
Introduction
This article is intented to illustrate the principles of data binding in .NET Windows Forms 2.0 as well as a description of data set and data-bound controls. Data binding techniques are sometimes one of the most important part of many enterprise applications and a lot of developers don't understand at all. Data binding is the mechanism for automatically associating and synchronizing data objects in memory with controls for presenting and gathering data from the user interface.
Most of the controls in Windows Forms architecture support data binding mechanism. They inherit from the Control class which implements the IBindableComponent interface which in turn supports a collection of binding objects (instances of the Binding class) through the Data bindings property as well as it allows the association of the underlying control with the binding context (a singleton instance of the BindingContext class) which synchronizes controls bound to the same data source. Complex controls can also add their implementation to advanced data binding scenarios through additional properties such as DataSource, DataMember, DisplayMember and ValueMember. This mechanisms enables to bind any control properties to a data source.
In order to setup data binding mechanism in Windows Forms, you need a data source. A data source is an in-memory business objects either comprises other business objects or it may be a single instance of a business object. The most common type of data source or business object in .NET is the instances of Dataset class or derived typed DataSet class.
The principles of Data binding
You can use the data binding mechanism to associate a business object to a control. In Windows Forms, data binding allows the data flow between the data sources and the data-bound control in two ways, namely, you present the data from the data source in the user interface, then interact with the control and change some values of its properties and finally those changes are reflected back in the underlying data source automatically.
In order to illustrate these concepts, we're going to use the AdventureWorks database shipped with the Microsoft SQL Server 2005 installation. First of all, let's create a Windows application using Visual Studio .NET 2005 IDE, and a type DataSet class to manage the Person.Contact, Purchasing.PurchaseOrderHeader and Purchasing.PurchaseOrderDetail tables representing the business entities Contact and Purchase Order as shown in Figure 1.

Figure 1
There are two forms of data binding in Windows Forms: simple and complex data binding. Simple data binding maps a property on a control (Text property of a TextBox control) to a property in a data source item. It shows only one row at a time.
This type of binding is represented by the Binding object. The constructor of the Binding class takes three parameters: the name of the control property, the data source, and the navigation path as shown in Listing 1. For example, let's bind individual columns columns within a table to the Text property of Textbox control.
Binding bdContactId = new Binding("Text", this.m_dsCRM, "Contact.ContactID"); this.m_tbContactId.DataBindings.Add(bdContactId); Binding bdContactLastName = new Binding("Text", this.m_dsCRM, "Contact.LastName"); this.m_tbContactLastName.DataBindings.Add(bdContactLastName);
Listing 1
The data source and the navigation path can be specified by different combinations, for instance in Listing 2, both binding construction statements will display the same information, although the way data source and navigation path are specified to the data binding mechanism is different for each of the two controls and it may cause problems with synchronization between the data-bound controls. The data binding mechanism creates a separate synchronization object (either a CurrencyManager for list data source or PropertyManager for individual object data sources) for each data source because the data sources are specified differently between the bindings.
In order to avoid this situation, you need to be consistent in the way you specify your data sources and navigation paths, and thus you get synchronized controls. I prefer to use the first option of the Listing 2.
Binding bdCustomerFullName = new Binding("Text", this.m_dsCRM, "Contact.LastName"); Binding bdCustomerFullName = new Binding("Text", this.m_dsCRM.Contact, "LastName");
Listing 2
Another approach to setting the DataBindings property of controls is to use the Visual Studio UI property dialog. For example, to set up the DataBinding property of the TextBox control m_tbContactId then click on the control and press F4 for the Property page. Click on the (DataBindings)/(Advanced) node in the property page (see Figure 2).

Figure 2
When you navigate to the correct data provider object (in this case, m_dsAdventureWorks, Contact.Lastname), then an instance of BindingSource object is created in Visual Studio 2005. The BindingSource class is explained in details below. You can also define the format of the data to be displayed in the control.
Complex data binding is the association of a list of data items bound to a control for the presentation of one or more properties at a time, thus it's important to display an entire rowset. Not all the controls support complex binding, and those in this category are of two types: grid controls (DataGridView in VS 2005 and DataGrid in VS 2003) and list controls such as ListBox, ListView and ComboBox.
Control which supports this type of binding has the DataSource and DataMember properties to map the data source to the control corresponding to the data source and navigation path arguments of the Binding constructor. Some of them have also the DisplayMember property to display the only one column of the table on the data source and ValueMember property that contains the encoded value that correspond to the DisplayMember as shown in Listing 3.
this.m_cbCombo.DataSource = this.m_dsCRM; this.m_cbCombo.DataMember = "Contact"; this.m_cbCombo.DisplayMember = "LastName"; this.m_cbCombo.ValueMember = "ContactID";
Listing 3
Synchronizing data between controls
When you create a binding, the form itself creates synchronization objects for the synchronization of multiple controls on the form bound to the same data source.
Every control has a BindingContext property that holds a collection of synchronization objects (instances of BindingManagerBase) for each data source that is used for data binding on the form. The BindingManagerBase class is the base for CurrencyManager for list-based data sources as well as PropertyManager class for individual custom business objects. You can use these classes to access underlying data, determine the current row and change the current row and affect all the controls bound to this data source.
In .NET 1.X, you had to deal directly with the BindingContext but in .NET 2.0 you don't.
Let's illustrate the concepts with an example. In order to retrieve a BindingContext instance, you pass a data source and optionally the navigation path. For example to reference the BindingManagerBase object associated to the data source and navigation path on the Listing 1, you must write the following code as shown in Listing 4.
BindingManagerBase bmbContact = this.BindingContext[this.m_dsCRM, "Contact"];
Listing 4
As you can see, it is almost the same parameters of the constructor of the Binding but dropping the final level of the BindingMember hierarchy. After you have a reference to the BindingManagerBase then you can set the Position property to move the cursor to records in the data provider.
In Visual Studio 2005 you can do the same operations easily using the BindingSource class and its underlying properties (Position, Current) and methods (MoveNext, MovePrevious) as shown below.
BindingSource class in .NET 2.0
As you can see before, you can spend a lot of time trying to manage data binding in .NET Framework 1.0 and 1.1 with Visual Studio 2003. Once of the most important features introduced in Framework 2.0 along with Visual Studio 2005 is the BindingSource class which is especially useful to deal with complex entities. BindingSource class serves several purposes:
- Another layer of abstraction between the bound controls (Win32 and ASP.NET controls) and data sources.
- A set of services to navigate through the rows, expose current row, pass current row values to bound controls, and pass updated values from bound controls to data sources.
- A set of services to filter and sort data.
An instance of BindingSource acts as a proxy between bound controls and their associated data source. You bind the controls on the form to a binding source and then the binding source to a data source. Let's translate the code written in Listing 1 to this new approach as shown in Listing 5.
//At the class level as an attribute. BindingSource m_bsContact = new BindingSource();
//At the initialization method. this.m_bsContact.DataSource = this.m_dsCRM; this.m_bsContact.DataMember = "Contact";
Binding bdContactId = new Binding("Text", this.m_bsContact, "ContactId"); this.m_tbContactId.DataBindings.Add(bdContactId);
Binding bdContactFullName = new Binding("Text", this.m_bsContact, "LastName"); this.m_tbContactLastName.DataBindings.Add(bdContactFullName);
Listing 5
It's remarkable to say that a lot of the code associated to BindingSource instances, as shown in Listing 5, can be generated using drag-and-drop mechanisms from the Data Source page to your Windows and ASP.NET forms.
The BindingSource class has a set of methods which allows navigating through the data source. In .NET 1.X, when you want to navigate the data source, you have to get a reference to the CurrencyManager object for the data source you are working with and change the value of the Position property as shown in Listing 6. This mechanism is still for backward compatibility with existing code.
BindingManagerBase bmbContact = this.BindingContext[this.m_dsCRM, "Contact"]; bmbContact.Position += 1;
Listing 6
In order to navigate the data source through the BindingSource object, you need to write the following statement as shown in Listing 7.
this.m_bsContact.MoveNext();
Listing 7
If you don't want to write this code for every application, you can use the new control available in .NET 2.0 BindingNavigator which is a special implementation of new ToolStrip control. It has toolbar button to navigate the data source (moving first, last, previous and next), an edit box to enter the position explicitly as well as buttons for adding, deleting and saving data items.
You can also fill a BindingSource with a data reader as well as with a DataTable by setting the DataSource and DataMember properties in Listing 8 and Listing 9.
string strConnString = "server=localhost;database=AdventureWorks;trusted_connection=true"; using (SqlConnection objConn = new SqlConnection(strConnString)) { SqlCommand objCmd = new SqlCommand("select ContactID, LastName, EMailAddress from Person.Contact", objConn); objConn.Open(); SqlDataReader objReader = objCmd.ExecuteReader(CommandBehavior.CloseConnection); BindingSource bsContact = new BindingSource(); bsContact.DataSource = objReader;
this.m_dgvContacts.DataSource = bsContact; this.m_tbContactLastName.Bindings.Add("Text", bsContact, "LastName"); } Listing 8 this.m_taContact.Fill(this.m_dsAdventureWorks.Contact); BindingSource bsContact = new BindingSource(); bsContact.DataSource = this.m_dsAdventureWorks; bsContact.DataMember = "Contact"; this.m_dgvContacts.DataSource = bsContact; this.m_tbContactLastName.Bindings.Add("Text", bsContact, "LastName");
Listing 9
It's remarkable to say that this approach is not a best practice to follow because it introduces a tight coupling between the presentation layer and the data access layer and this new mechanism is useful when dealing with complex hierarchies of bound controls.
Representing Entities in a Form
In any data model, it is common to find complex business entities which are depicted as one-to-many relationships. The classic example is the complex business entity Order, which is typically represented by OrderHeader and OrderDetails tables that have a one-to-many relationship like it's represented in our data set in the Figure 1. You can also find relationships between business entities which are modeled as one-to-many relationship.
The classic approach for representing these complex business entities or the one-to-many relationship between entities in forms is named master-detail. It allows displaying a single row of the one-side (master) of the relationship and the many-side (detail) is either displayed one of them at time and allow the user to navigate among them or you can display them using a list control such as DataGridView, ListBox, ListView or TreeView controls.
You can achieve master-detail data binding by dragging and dropping the PurchaseOrderHeader entity from the Data Sources windows into the target form in a Details form (see Figure 3) and the PurchaseOrderDetail in DataGridView form (see Figure 4). Then run the application and see the results (see Figure 5).

Figure 3

Figure 4

Figure 5
You can achieve the same results programmatically using a technique named Chaining Binding Sources for master-detail data binding. You need to chain together two binding sources, with one binding source bound to the parent data source, and the child binding source bound to the parent binding source, and setting the data member property of the child binding source to the property name to the actual name of the data relation between the parent and the child (see Listing 10).
this.purchaseOrderHeaderBindingSource.DataSource = this.sales_DS; this.purchaseOrderHeaderBindingSource.DataMember = "PurchaseOrderHeader"; this.purchaseOrderDetailBindingSource.DataSource = this.purchaseOrderHeaderBindingSource; this.purchaseOrderDetailBindingSource.DataMember = "FK_PurchaseOrderDetail_PurchaseOrderHeader_PurchaseOrderID";
Listing 10
One-To-One relationship
This type of relationship is relatively rare in relational database. There are used to represent the object-oriented concept of inheritance. Some database designers include all the attributes of the subtype and base type entities in one entity represented by a relational table but there is the drawback of sparse arrays- many rows where the majority of the columns are empty. This problem can increase if the inheritance involves several subtypes.
For example, let's illustrate the concepts supposing that we model the Person base entity (base class of Person), and two other subtypes Seller and Customer (classes of Seller and Customer). A Seller instance is also a Person as well as a Customer instance is also a Person.
One way to deal with this problem is based on the assumption that users will almost always be concentrating in an Entity instance at time, so you need to forms: one to display the properties of the Seller entities and another one to display the properties of Customer. Of course, you need to make it easy to navigate between the two forms.
You need to add a discriminator field to the base entity Person as well as it's a best practice (and it's also logic according to the object-oriented concepts that an object has an identity independently of its classification) to use the same primary key as the identifier of entities in the underlying tables representing the base and subtype entities and define a foreign key relationship to enforce referential integrity between the parent table (base entity) and the children tables (subtypes entities). This model can be done easily using the E/R Studio modelling tool (see Figure 6).

Figure 6
Finally, you apply the same techniques explained in one-to-many relationship section (see Figure 7).

Figure 7
Many-To-Many relationship
You can find many-to-many relationships modeling the relationship between business entities but it is not common to find many-to-many relationship representing one complex business entity instead it represents relationships between entities.
One solution is to use a pair of a list controls and allow the user to determine which one filters the other. Another solution is to flatten the many-to-many into a one-to-many relationship. The one-side part is determined from the point of view of the business process associated to the application. The approach is to ignore the many-to-many relationship and resolve it pretending to be working with a one-to-many relationship.
Let's illustrate the concepts by modelling the relationship between a Person and its Role in an organization. A person may play many roles and a role may contain many persons. You can model the many-to-many relationship in the logical data model as non-specific relationship in E/R Studio (see).
When the physical model is generated from the logical model, then a join table is establish the many-to-many relationship between the entities (see Figure 8).

Figure 8
In order to represent these entities in a form, the first step is to determine the point of view of the user from the model of the business process (which side of the relationship is most import for the user). Let's suppose the user is working with roles and he wants to see its underlying Persons. It's remarkable to say that it's not common to require representing both entities at the same time. The next step is to flatten the many-to-many relationship. In this case, the one-side of the relationship is the Role table and the many-side of the relationship is virtual many-side created by joining the join-table to the Person table (see Listing 11).
select [Person Role].RoleID, [Person].* from [Person Role] inner join [Person] on [Person Role].PersonID=[Person].PersonID;
Listing 11
Now let's define the DataSet with the tables Role and the virtual table represented by the query in Listing 11. The final DataSet is depicted in Figure 9.

Figure 9
Let's see the final result in Figure 10.

Figure 10
Conclusion
In this article, I deeply discussed the key methodologies and techniques to develop enterprise application using data-binding in .NET Framework for Windows Forms application. I also covered the topic of representing business entities that are persisted in a relational database system onto a Windows Forms and how to use RAD techniques to achieve this goal in order to increase the productivity. After you read this article, you have an insight of data-binding in .NET Framework, and you can begin to develop your customized solutions easily.
|
|
|
Login
to add your contents and source code to this article
|
|
|
|
|
|
|
|
|
|
|
|
John Charles Olamendy
He’s a senior Integration Solutions Architect and Consultant. His primary area of involvement is in Object-Oriented Analysis and Design, Database design , Enterprise Application Integration, Unified Modeling Language, Design Patterns and Software Development Process. He has knowledge and extensive experience in the development of Enterprise Applications using Microsoft.NET and J2EE technologies and standards. He is proficient with distributed systems programming; and business-process integration and messaging using the principles of the Services Oriented Architecture (SOA) and related technologies such as Microsoft BizTalk Server, Web Services (Windows Communication Foundation, WSE, BEA WebLogic, Oracle AS and Axis) through multiple implementations of loosely-coupled system. He’s a prolific blogger contributing to .NET and J2EE communities and actively writes articles on subjects relating to integration of applications, business intelligence, and enterprise applications development. He holds a Master’s degree in Business Informatics at Otto Von Guericke University, Magdeburg, Germany. He was recently awarded as MVP. He currently works in the telecommunication industry and delivers integration solutions for this industry. He harbors a true passion for the technology.
|
|
|
|
|
|
|
|
|
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional
consulting company, our consultants are well-known experts in .NET and many of them
are MVPs, authors, and trainers. We specialize in Microsoft .NET development and
utilize Agile Development and Extreme Programming practices to provide fast pace
quick turnaround results. Our software development model is a mix of Agile Development,
traditional SDLC, and Waterfall models.
|
|
Click here to learn more about C# Consulting. |
|
|
|
|
|
|
|
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon.
Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees.
As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
|
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
|
Boost the performance of your .NET applications
“ANTS Profiler took us straight to the specific areas of our code which were the cause of our performance issues." Terry Phillips, Sr. Developer, Harley-Davidson Dealer Systems. Download your free trial of ANTS Profiler.
|
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
|
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today. With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications. Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|