How to: Bind a Windows Forms Control to a Factory Object

When you are building controls that interact with data, you will sometimes find it necessary to bind a control to an object or method that generates other objects. Such an object or method is called a factory. Your data source might be, for example, the return value from a method call, instead of an object in memory or a type. You can bind a control to this kind of data source as long as the source returns a collection.

You can easily bind a control to a factory object by using the BindingSource control.

Example

The following example demonstrates how to bind a DataGridView control to a factory method by using a BindingSource control. The factory method is named GetOrdersByCustomerId, and it returns all the orders for a given customer in the Northwind database.

#using <System.dll>
#using <System.Data.dll>
#using <System.Drawing.dll>
#using <System.EnterpriseServices.dll>
#using <System.Transactions.dll>
#using <System.Windows.Forms.dll>
#using <System.Xml.dll>
using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::ComponentModel;
using namespace System::Data;
using namespace System::Data::Common;
using namespace System::Data::SqlClient;
using namespace System::Diagnostics;
using namespace System::Drawing;
using namespace System::Windows::Forms;

// This form demonstrates using a BindingSource to bind to a factory
// object.
public ref class Form1: public System::Windows::Forms::Form
{
private:

   // This is the TextBox for entering CustomerID values.
   static TextBox^ customerIdTextBox = gcnew TextBox;

   // This is the DataGridView that displays orders for the
   // specified customer.
   static DataGridView^ customersDataGridView = gcnew DataGridView;

   // This is the BindingSource for binding the database query
   // result set to the DataGridView.
   static BindingSource^ ordersBindingSource = gcnew BindingSource;

public:
   Form1()
   {
      // Set up the CustomerID TextBox.
      this->customerIdTextBox->Dock = DockStyle::Bottom;
      this->customerIdTextBox->Text =
         L"Enter a valid Northwind CustomerID, for example: ALFKI,"

      L" then TAB or click outside the TextBox";
      this->customerIdTextBox->Leave += gcnew EventHandler(
         this, &Form1::customerIdTextBox_Leave );
      this->Controls->Add( this->customerIdTextBox );
      
      // Set up the DataGridView.
      customersDataGridView->Dock = DockStyle::Top;
      this->Controls->Add( customersDataGridView );
      
      // Set up the form.
      this->Size = System::Drawing::Size( 800, 800 );
      this->Load += gcnew EventHandler( this, &Form1::Form1_Load );
   }

private:
   // This event handler binds the BindingSource to the DataGridView
   // control's DataSource property.
   void Form1_Load(
      System::Object^ /*sender*/,
      System::EventArgs^ /*e*/ )
   {
      // Attach the BindingSource to the DataGridView.
      this->customersDataGridView->DataSource =
         this->ordersBindingSource;
   }

public:
   // This is a static factory method. It queries the Northwind
   // database for the orders belonging to the specified
   // customer and returns an IList.
   static System::Collections::IList^ GetOrdersByCustomerId( String^ id )
   {
      // Open a connection to the database.
      String^ connectString = L"Integrated Security=SSPI;"
      L"Persist Security Info=False;Initial Catalog=Northwind;"
      L"Data Source= localhost";
      SqlConnection^ connection = gcnew SqlConnection;
      connection->ConnectionString = connectString;
      connection->Open();
      
      // Execute the query.
      String^ queryString = String::Format(
         L"Select * From Orders where CustomerID = '{0}'", id );
      SqlCommand^ command = gcnew SqlCommand( queryString,connection );
      SqlDataReader^ reader = command->ExecuteReader(
         CommandBehavior::CloseConnection );
      
      // Build an IList from the result set.
      List< DbDataRecord^ >^ list = gcnew List< DbDataRecord^ >;
      System::Collections::IEnumerator^ e = reader->GetEnumerator();
      while ( e->MoveNext() )
      {
         list->Add( dynamic_cast<DbDataRecord^>(e->Current) );
      }

      return list;
   }

   // This event handler is called when the user tabs or clicks
   // out of the customerIdTextBox. The database is then queried
   // with the CustomerID in the customerIdTextBox.Text property.
private:
   void customerIdTextBox_Leave( Object^ /*sender*/, EventArgs^ /*e*/ )
   {
      // Attach the data source to the BindingSource control.
      this->ordersBindingSource->DataSource = GetOrdersByCustomerId(
         this->customerIdTextBox->Text );
   }

public:
   [STAThread]
   static void main()
   {
      Application::EnableVisualStyles();
      Application::Run( gcnew Form1 );
   }
};
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Drawing;
using System.Data.SqlClient;
using System.Windows.Forms;

// This form demonstrates using a BindingSource to bind to a factory
// object. 
public class Form1 : System.Windows.Forms.Form
{
    // This is the TextBox for entering CustomerID values.
    private TextBox customerIdTextBox = new TextBox();

    // This is the DataGridView that displays orders for the 
    // specified customer.
    private DataGridView customersDataGridView = new DataGridView();

    // This is the BindingSource for binding the database query
    // result set to the DataGridView.
    private BindingSource ordersBindingSource = new BindingSource();

    public Form1()
    {
        // Set up the CustomerID TextBox.
        this.customerIdTextBox.Location = new Point(100, 200);
        this.customerIdTextBox.Size = new Size(500, 30);
        this.customerIdTextBox.Text =
            "Enter a valid Northwind CustomerID, for example: ALFKI," +
            " then RETURN or click outside the TextBox";
        this.customerIdTextBox.Leave +=
            new EventHandler(customerIdTextBox_Leave);
        this.customerIdTextBox.KeyDown +=
            new KeyEventHandler(customerIdTextBox_KeyDown);
        this.Controls.Add(this.customerIdTextBox);
       
        // Set up the DataGridView.
        customersDataGridView.Dock = DockStyle.Top;
        this.Controls.Add(customersDataGridView);

        // Set up the form.
        this.Size = new Size(800, 500);
        this.Load += new EventHandler(Form1_Load);
    }

    // This event handler binds the BindingSource to the DataGridView
    // control's DataSource property.
    private void Form1_Load(
        System.Object sender,
        System.EventArgs e)
    {
        // Attach the BindingSource to the DataGridView.
        this.customersDataGridView.DataSource =
            this.ordersBindingSource;
    }

    // This is a static factory method. It queries the Northwind 
    // database for the orders belonging to the specified
    // customer and returns an IEnumerable.
    public static IEnumerable GetOrdersByCustomerId(string id)
    {
        // Open a connection to the database.
        string connectString = "Integrated Security=SSPI;" +
            "Persist Security Info=False;Initial Catalog=Northwind;" +
            "Data Source= localhost";
        SqlConnection connection = new SqlConnection();
       
        connection.ConnectionString = connectString;
        connection.Open();

        // Execute the query.
        string queryString =
            String.Format("Select * From Orders where CustomerID = '{0}'",
            id);
        SqlCommand command = new SqlCommand(queryString, connection);
        SqlDataReader reader =
            command.ExecuteReader(CommandBehavior.CloseConnection);
        return reader;
               
    }

    // These event handlers are called when the user tabs or clicks
    // out of the customerIdTextBox or hits the return key.
    // The database is then queried with the CustomerID
    //  in the customerIdTextBox.Text property.
    void customerIdTextBox_Leave(object sender, EventArgs e)
    {
        // Attach the data source to the BindingSource control.
        this.ordersBindingSource.DataSource =
            GetOrdersByCustomerId(this.customerIdTextBox.Text);
    }

    void customerIdTextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Return)
        {
            // Attach the data source to the BindingSource control.
            this.ordersBindingSource.DataSource =
                GetOrdersByCustomerId(this.customerIdTextBox.Text);
        }
    }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }
}
Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Diagnostics
Imports System.Drawing
Imports System.Data.SqlClient
Imports System.Windows.Forms

' This form demonstrates using a BindingSource to bind to a factory
' object. 

Public Class Form1
    Inherits System.Windows.Forms.Form
    ' This is the TextBox for entering CustomerID values.
    Private WithEvents customerIdTextBox As New TextBox()
    
    ' This is the DataGridView that displays orders for the 
    ' specified customer.
    Private customersDataGridView As New DataGridView()
    
    ' This is the BindingSource for binding the database query
    ' result set to the DataGridView.
    Private ordersBindingSource As New BindingSource()
    
    Public Sub New() 

        ' Set up the CustomerID TextBox.
        Me.customerIdTextBox.Location = New Point(100, 200)
        Me.customerIdTextBox.Size = New Size(500, 30)
        Me.customerIdTextBox.Text = _
            "Enter a valid Northwind CustomerID, for example: ALFKI," & _
            " then RETURN or click outside the TextBox"
        Me.Controls.Add(Me.customerIdTextBox)
        
        ' Set up the DataGridView.
        customersDataGridView.Dock = DockStyle.Top
        Me.Controls.Add(customersDataGridView)
        
        ' Set up the form.
        Me.Size = New Size(800, 500)
    End Sub
    
    ' This event handler binds the BindingSource to the DataGridView
    ' control's DataSource property.
    Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Me.Load

        ' Attach the BindingSource to the DataGridView.
        Me.customersDataGridView.DataSource = Me.ordersBindingSource

    End Sub
    
    ' This is a static factory method. It queries the Northwind 
    ' database for the orders belonging to the specified
    ' customer and returns an IEnumerable.
    Public Shared Function GetOrdersByCustomerId(ByVal id As String) _
        As IEnumerable

        ' Open a connection to the database.
        Dim connectString As String = "Integrated Security=SSPI;" & _
             "Persist Security Info=False;Initial Catalog=Northwind;" & _
             "Data Source= localhost"
        Dim connection As New SqlConnection()

        connection.ConnectionString = connectString
        connection.Open()

        ' Execute the query.
        Dim queryString As String = _
            String.Format("Select * From Orders where CustomerID = '{0}'", id)
        Dim command As New SqlCommand(queryString, connection)
        Dim reader As SqlDataReader = _
            command.ExecuteReader(CommandBehavior.CloseConnection)
        Return reader

    End Function
     
    ' These event handlers are called when the user tabs or clicks
    ' out of the customerIdTextBox or hits the return key.
    ' The database is then queried with the CustomerID
    '  in the customerIdTextBox.Text property.
    Private Sub customerIdTextBox_Leave(ByVal sender As Object, _
        ByVal e As EventArgs) Handles customerIdTextBox.Leave

        ' Attach the data source to the BindingSource control.
        Me.ordersBindingSource.DataSource = _
            GetOrdersByCustomerId(Me.customerIdTextBox.Text)

    End Sub
    
    
    Private Sub customerIdTextBox_KeyDown(ByVal sender As Object, _
        ByVal e As KeyEventArgs) Handles customerIdTextBox.KeyDown

        If e.KeyCode = Keys.Return Then

            ' Attach the data source to the BindingSource control.
            Me.ordersBindingSource.DataSource = _
                GetOrdersByCustomerId(Me.customerIdTextBox.Text)
        End If

    End Sub

    <STAThread()> _
    Shared Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New Form1())

    End Sub
End Class

Compiling the Code

This example requires:

  • References to the System, System.Data, System.Drawing and System.Windows.Forms assemblies.

For information about building this example from the command line for Visual Basic or Visual C#, see Building from the Command Line or Command-line Building With csc.exe. You can also build this example in Visual Studio by pasting the code into a new project. Also see How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio.

See Also

BindingNavigator
DataGridView
BindingSource
BindingSource Component
How to: Bind a Windows Forms Control to a Type