Data Binding

 
Chapter 10 - Viewing .NET Data
bySimon Robinsonet al.
Wrox Press 2002
  

The previous examples have all used the DataGrid control, which is only one of the controls within the .NET runtime that can be used to display data. The process of linking a control to a data source is called data binding .

If you have any experience with programming Windows applications in MFC, at one time or another, you'll probably have utilized the Dialog Data Exchange ( DDX ) capabilities, to hook member variables of one class to a Win32 control. You'll probably be pleased to know that you can close the door on DDX, as it's considerably easier to hook data to controls in .NET. You can bind data not only to Windows controls, but also to web pages using ASP.NET. Binding controls to web pages will be covered in Chapter 14.

Simple Binding

A control that supports single binding typically displays only a single value at once, such as a textbox or radio button. The following example shows how to bind a column from a DataTable to a TextBox :

   DataSet ds = CreateDataSet();     textBox1.DataBindings.Add("Text", ds , "Products.ProductName");   

After retrieving some data from the Products table and storing this in the returned DataSet with the CreateDataSet() method as above, the second line then binds the Text property of the control ( textBox1 ) to the Products.ProductName column. If you were to write this code and retrieve data from the Northwind database, you would see something like the following on screen:

click to expand

The textbox is indeed displaying something from the database. To check that it is the right column and value, you could use the SQL Server Query Analyzer tool to verify the contents of the Products table:

click to expand

Having a single text box on screen with no way to scroll to the next or the previous record and no way to update the database is not very useful, so the next section will show a more realistic example, and introduce the other objects that are necessary in order for data binding to work. I'll begin with an overview of some of the classes used.

Data Binding Objects

The diagram overleaf shows a class hierarchy for the objects that are used in data binding. In this section we'll discuss the BindingContext , CurrencyManager, and PropertyManager classes of the System.Windows.Forms namespace, and show how they interact when data is bound to one or more controls on a form. The shaded objects are those that are utilized in binding.

click to expand

In the previous example, we used the DataBindings property of the TextBox control to bind a column from a DataSet to the Text property of the control. The DataBindings property is an instance of the ControlBindingsCollection shown above:

   textBox1.DataBindings.Add("Text", ds, "Products.ProductName");   

This line added a Binding object to the ControlBindingsCollection .

Binding Context

Each Windows form has a BindingContext property. Incidentally, Form is derived from Control , which is where this property is actually defined, so most controls have this property. A BindingContext object has a collection of BindingManagerBase instances. These instances are created and added to the binding manager object when a control is data bound:

click to expand

The BindingContext may contain several data sources, wrapped in either a CurrencyManager or a PropertyManager . The decision on which class is used is based on the data source itself.

If the data source contains a list of items, such as a DataTable , DataView , or any object that implements the IList interface, then a CurrencyManager will be used, as this can maintain the current position within that data source. If the data source returns only a single value then a PropertyManager will be stored within the BindingContext .

A CurrencyManager or PropertyManager is only created once for a given data source. If you bind two textboxes to a row from a DataTable , only one CurrencyManager will be created within the binding context.

Each control added to a form is linked to the form's binding manager, so all controls share the same instance. When a control is initially created, its BindingContext property is null . When the control is added to the Controls collection of the form, this sets the BindingContext to that of the form.

To bind a control to a form, you need to add an entry to its DataBindings property, which is an instance of ControlBindingsCollection . The code shown below creates a new binding:

   textBox1.DataBindings.Add("Text", ds, "Products.ProductName");   

Internally, the Add() method of ControlBindingsCollection creates a new instance of a Binding object from the parameters passed to this method, and adds this to the bindings collection:

click to expand

The image above shows roughly what is going on when you add a Binding to a Control . The binding links the control to a data source, which is maintained within the BindingContext of the Form (or control itself). Changes within the data source are reflected into the control, as are changes in the control.

Binding

This class links a property of the control to a member of the data source. When that member changes, the control's property is updated to reflect this change. The opposite is also true if the text within the textbox is updated, this change is reflected in the data source.

Bindings can be set up from any column to any property of the control, so, for instance, you would bind a column to a textbox and could also bind another column to the textbox color (or length).

You could bind properties of a control to completely different data sources maybe the color of the cell is defined in a colors table, and the actual data is defined within another table.

CurrencyManager and PropertyManager

When a Binding object is created, a corresponding CurrencyManager or PropertyManager object will also be created if this is the first time that data from the given source has been bound. The purpose of this class is to define the position of the "current" record within the data source, and to coordinate all list bindings when this current record is changed.

The following example displays two fields from the Products table, and includes a way to move between records by means of a TrackBar control:

click to expand

The example code for this application is shown in its entirety. The code is available in the \09_ScrollingDataBinding directory:

   using System;     using System.Windows.Forms;     using System.Data;     using System.Data.SqlClient;     public class ScrollingDataBinding : System.Windows.Forms.Form     {     private Button retrieveButton;     private TextBox textName;     private TextBox textQuan;     private TrackBar trackBar;     private DataSet ds;   

The application creates the window, and all controls for that window, within the ScrollingDataBinding constructor:

   public ScrollingDataBinding()     {     this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);     this.ClientSize = new System.Drawing.Size(464, 253);     this.Text = "09_ScrollingDataBinding";     this.retrieveButton = new Button();     retrieveButton.Location = new System.Drawing.Point(4, 4);     retrieveButton.Size = new System.Drawing.Size(75, 23);     retrieveButton.TabIndex = 1;     retrieveButton.Anchor = AnchorStyles.Top  AnchorStyles.Left;     retrieveButton.Text = "Retrieve";     retrieveButton.Click += new System.EventHandler     (this.retrieveButton_Click);     this.Controls.Add(this.retrieveButton);     this.textName = new TextBox();     textName.Location = new System.Drawing.Point(4, 31);     textName.Text = "Please click retrieve...";     textName.TabIndex = 2;     textName.Anchor = AnchorStyles.Top  AnchorStyles.Left     AnchorStyles.Right ;     textName.Size = new System.Drawing.Size(456, 20);     textName.Enabled = false;     this.Controls.Add(this.textName);     this.textQuan = new TextBox();     textQuan.Location = new System.Drawing.Point(4, 55);     textQuan.Text = "";     textQuan.TabIndex = 3;     textQuan.Anchor = AnchorStyles.Top  AnchorStyles.Left     AnchorStyles.Top;     textQuan.Size = new System.Drawing.Size(456, 20);     textQuan.Enabled = false;     this.Controls.Add(this.textQuan);     this.trackBar = new TrackBar();     trackBar.BeginInit();     trackBar.Dock = DockStyle.Bottom ;     trackBar.Location = new System.Drawing.Point(0, 275);     trackBar.TabIndex = 4;     trackBar.Size = new System.Drawing.Size(504, 42);     trackBar.Scroll += new System.EventHandler(this.trackBar_Scroll);     trackBar.Enabled = false;     this.Controls.Add(this.trackBar);     }   

When the Retrieve button is clicked, the event handler selects all records from the Products table, and stores this data within the private dataset ds :

   protected void retrieveButton_Click(object sender, System.EventArgs e)     {     retrieveButton.Enabled = false ;     ds = CreateDataSet();   

Next, the two text controls are bound:

   textName.DataBindings.Add("Text" , ds ,     "Products.ProductName");     textQuan.DataBindings.Add("Text" , ds ,     "Products.QuantityPerUnit");     trackBar.Minimum = 0 ;     trackBar.Maximum = this.BindingContext[ds,"Products"].Count  1;     textName.Enabled = true;     textQuan.Enabled = true;     trackBar.Enabled = true;     }   

Here we have a trivial record scrolling mechanism, which responds to movements of the TrackBar thumb:

   protected void trackBar_Scroll(object sender , System.EventArgs e)     {     this.BindingContext[ds,"Products"].Position = trackBar.Value;     }     private DataSet CreateDataSet()     {     string source = "server=(local)\NetSDK;" +     "uid=QSUser;pwd=QSPassword;" +     "database=northwind";     string customers = "SELECT * FROM Products";     SqlConnection con = new SqlConnection(source);     SqlDataAdapter da = new SqlDataAdapter(customers , con);     DataSet ds = new DataSet();     da.Fill(ds , "Products");     return ds;     }     static void Main()     {     Application.Run(new ScrollingDataBinding());     }     }   

When the data is originally retrieved, the maximum position on the track bar is set to be the number of records. Then, in the scroll method above, we set the position of the BindingContext for the products DataTable to the position of the scroll bar thumb. This effectively changes the current record from the DataTable , so all controls bound to the current row (in this example the two textboxes) are updated.

In this section we've covered binding to various data sources, such as arrays, data tables, data views, and various other containers of data, how to sort and filter that data, and how the underlying binding mechanism in .NET works. In the next section we'll discuss how Visual Studio has been extended to permit data access to be better integrated with the application.

  


Professional C#. 2nd Edition
Performance Consulting: A Practical Guide for HR and Learning Professionals
ISBN: 1576754359
EAN: 2147483647
Year: 2002
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net