Notification windows:
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:
- NHibernate (An open source ORM framework)
- ObjectViews (An open source data binding framework)
- 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
databinder1.StartProgress()
databinder1.StopProgress()
C#
databinder1.StartProgress();
databinder1.StopProgress();
For binding the control to any data source that implements the ICollection
of IList
, use the following syntax:
VB
DataBinder1.DAOObject = session
DataBinder1.EntityType = GetType(User)
DataBinder1.DataSource = objectList
datagrid1.DataSource = DataBinder1.BindSource
DataBinder1.SetBinding()
DataBinder1.ShowNotification=True
C#
DataBinder1.DAOObject = session;
DataBinder1.EntityType = GetType(User);
DataBinder1.DataSource = objectList;
datagrid1.DataSource = DataBinder1.BindSource;
DataBinder1.SetBinding();
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)()
Private Sub ldr_Cancelled() Handles ldr.Cancelled
MessageBox.Show("Operation cancelled")
DataBinder1.StopProgress()
End Sub
Private Sub ldr_Finished() Handles ldr.Finished
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)();
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() {
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.