Introduction
Due to the large number of records I deal with in my applications, the ability to suspend DataBindings is key to performance. I have often spent too much time making sure I am suspending DataBindings for all areas of my app. It is common to have a dozen or more active screens with a Binding Context.
One common reason for suspending binding is to be able to make changes to multiple fields before validation occurs. Those cases can be handled on a 'one on one' basis as business logic dictates.
There are a myriad of events that can fire off on bound controls when you're populating a dataset, both on grids and individual controls. I have found a significant performance increase when I suspend Bindings as I'm loading data, or when I'm clearing data.
CollectionWithEvents
This is a class that inherits from CollectionBase
and provides events for the collection. The CurrencyManagerCollection
class inherits from CollectionWithEvents
.
using System;
using System.Collections;
namespace Assemblies.UserInterfaceArchitecture
{
public class CollectionWithEvents : CollectionBase
{
public delegate void CollectionClear();
public delegate void CollectionChange(int index, object value);
public event CollectionClear Clearing;
public event CollectionClear Cleared;
public event CollectionChange Inserting;
public event CollectionChange Inserted;
public event CollectionChange Removing;
public event CollectionChange Removed;
protected override void OnClear()
{
if (Clearing != null) Clearing();
}
protected override void OnClearComplete()
{
if (Cleared != null) Cleared();
}
protected override void OnInsert(int index, object value)
{
if (Inserting != null) Inserting(index, value);
}
protected override void OnInsertComplete(int index, object value)
{
if (Inserted != null) Inserted(index, value);
}
protected override void OnRemove(int index, object value)
{
if (Removing != null) Removing(index, value);
}
protected override void OnRemoveComplete(int index, object value)
{
if (Removed != null) Removed(index, value);
}
}
}
CurrencyManagerCollection
using System;
using System.Data ;
using System.Windows.Forms ;
Assemblies.UserInterfaceArchitecture
{
public class CurrencyManagerCollection : CollectionWithEvents
{
public void SuspendBindings()
{
foreach (CurrencyManager cm in this)
{
cm.SuspendBinding() ;
}
}
public void ResumeBindings()
{
foreach (CurrencyManager cm in this)
{
cm.ResumeBinding() ;
}
}
public int Add(CurrencyManager value)
{
if (Contains(value) == false)
{
return base.List.Add(value as object);
}
return 0 ;
}
public void Remove(CurrencyManager value)
{
base.List.Remove(value as object);
}
public void Insert(int index, CurrencyManager value)
{
base.List.Insert(index, value as object);
}
public bool Contains(CurrencyManager value)
{
return base.List.Contains(value as object);
}
public CurrencyManager this[int index]
{
get { return (base.List[index] as CurrencyManager); }
}
}
}
Usage
As the events are firing off in your controls/forms that set up DataBindings, all you need to do is add the CurrencyManger
to the collection. Some examples of this are shown below:
mainClass.CurrencyManagers.Add(((CurrencyManager)
this.BindingContext[TheDataView]));
mainClass.CurrencyManagers.Add(((CurrencyManager)
this.BindingContext[TheDataTable]));
mainClass.CurrencyManagers.Add(currencyManager);
As you're preparing to load data into your DataSet
(hopefully it will be a strongly-typed DataSet
!), you can to the following:
mainClass.CurrencyManagers.SuspendBindings() ;
mainClass.CurrencyManagers.ResumeBindings() ;
In some cases I don't want to suspend bindings on everything in the application, but when I do, I know that all my databound controls will be suspended!