Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Asynchronous data loading and data binding with Windows Forms

0.00/5 (No votes)
15 Dec 2008 1  
This article introduces a reusable library that contains two utility components for data binding and asynchronous data loading.

Screen01.JPG

Notification windows:

Deleted.JPGSaved.JPG

Error.jpg

Introduction

This article introduces a reusable library that contains two utility components I developed for performing data binding and asynchronous data loading with WinForms applications. The components I am introducing here are provided on an as-is basis, and are not claiming to follow any standard design pattern. However, they were developed to avoid some duplicate coding efforts that are required to implement simple binding scenarios in Window Forms applications. The article is solely based on Windows application environment.

Prerequisites

The components described in the article use three open source implementations:

  1. NHibernate (An open source ORM framework)
  2. ObjectViews (An open source data binding framework)
  3. NofifyWindow (A library posted in CP by Mr. Robert Misiak)

I would like to express my gratitude to these valuable frameworks and libraries, integrating which I have implemented the small utility components described in the article content below.

Background

If you've developed a WinForms application with data binding, you've encountered the daunting task of implementing a data binding feature supported throughout the application. Implementing the replicated methods for saving and deleting data as well as error handling is a boring and very bug-prone process when you are building something more exquisite than a demo test application. After my jiggling experiments with data binding, I developed two utility components:

1. Data Binder

It has all required features for a data navigator as well as to handle save, delete, and error handling. It also provides notification using a notify window.

2. Data Loader

It is a runtime invisible type of component that implements an async data loading behavior using a background worker, and provides some event notifications to consume the data fetched by the async operation.

Using the code

Data binder

It is a component with a user interface, hence we can create a new instance by using the toolbox of the Window Forms Designer. To add the control to the toolbox, select Choose Items from the context menu of the toolbox, and browse to the complied library (DataBinder.dll) of the attached project. After adding the control to a Windows Form, you can call the StartProgress and StopProgress methods to display and hide the progress bar.

VB

'It will display the progress bar
databinder1.StartProgress()

'It will hide the progress bar
databinder1.StopProgress()

C#

//It will display the progress bar
databinder1.StartProgress();

//It will hide the progress bar
databinder1.StopProgress();

For binding the control to any data source that implements the ICollection of IList, use the following syntax:

VB

'This must be NHibernate session, an instance of ISession
DataBinder1.DAOObject = session
'This is type of entity that needs to be persisted
DataBinder1.EntityType = GetType(User)
'It contains any collection of entities
DataBinder1.DataSource = objectList
datagrid1.DataSource = DataBinder1.BindSource
'This will enable data binding between 
'UI controls and internal ObjectView instance
DataBinder1.SetBinding()
'This will enable the notification window 
'for and save and delete operation
DataBinder1.ShowNotification=True

C#

//This must be NHibernate session, an instance of ISession
 DataBinder1.DAOObject = session;
//This is type of entity that needs to be persisted
 DataBinder1.EntityType = GetType(User);
//It contains any collection of entities
DataBinder1.DataSource = objectList;
datagrid1.DataSource = DataBinder1.BindSource;
//This will enable data binding between UI controls
//and internal ObjectView instance
DataBinder1.SetBinding();
//This will enable the notification window for and save and delete operation
DataBinder1.ShowNotification=True;

That's all that is required to keep running the data binder control.

Data loader

This component does not have a visible user interface, hence we can directly create an instance like any other variable declaration. The component supports generic declarations, so any valid entity (POCO) can be used to create a DataLoader instance; e.g.,

VB

Dim ldr as New DataUtils.DataLoader(Of User)()
'After creating instance of DataLoader, 
'event subscription is required to catch some usefull
'events notification like Cancelled,Finished 

Private Sub ldr_Cancelled() Handles ldr.Cancelled
  MessageBox.Show("Operation cancelled")
  DataBinder1.StopProgress()
End Sub

Private Sub ldr_Finished() Handles ldr.Finished
    'Put any data binding code here
    userDataBinder.StopProgress()
End Sub

Private Sub ldr_LoadError(ByVal e As System.Exception) Handles ldr.LoadError
    MessageBox.Show(e.Message, "Error")
    DataBinder1.StopProgress()
End Sub

C#

private DataUtils.DataLoader(Of User) ldr = 
               New DataUtils.DataLoader(Of User)();
//After creating instance of DataLoader, 
//event subscription is required to catch some usefull
//events notification like Cancelled,Finished 
ldr.Cancelled+=new CancelledEventHandler(ldr_Cancelled)
ldr.Finished+=new FinishedEventHandler(ldr_Finished)
ldr.LoadErrod+=new LoadErrorEventHandler(ldr_LoadError)

private void ldr_Cancelled() {
        MessageBox.Show("Operation cancelled");
        DataBinder1.StopProgress();
    }

    private Sub ldr_Finished() {
        //Put any data binding code here
        userDataBinder.StopProgress();
}

private Sub ldr_LoadError(System.Exception e) {
    MessageBox.Show(e.Message, "Error");
    DataBinder1.StopProgress();
}

Every data loader instance requires an NHibernate Session instance to fetch the data from the persistent store.

VB

ldr.Session = session

C#

ldr.Session = session;

Now, as a last resort, invoke the FetchAll method that will internally create a background worker and start fetching data records asynchronously. Meanwhile, the application may display a responsive UI, or may indulge in some other task. Once the data fetching gets completed, the application will receive a Finished or LoadError event depending on the outcome of the data retrieval operations.

VB

ldr.FetchAll()

C#

ldr.FetchAll();

That's all that is required for running a data loader component.

Although I have tried to keep the quality of this article on CP, I still believe that the components shared by the article does not follow any standard Design Pattern, and may not be efficient enough for providing a scalable solution. Anyways, I thought that it might be useful for someone, and might avoid some duplicate coding efforts.

Please share your view and comments related to this article; I will be happy to listen all those blessings. :)

History

  • Initial revision - Dec. 16 2008.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here