65.9K
CodeProject is changing. Read more.
Home

CurrencyManager Collection - Dealing with SuspendBinding and ResumeBinding

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.33/5 (3 votes)

Jun 21, 2005

CPOL

1 min read

viewsIcon

56421

Manage SuspendBindings and ResumeBindings for all CurrencyManagers in your app.

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
{
  // summary
  // Base class for managing strongly typed collections
  // summary
  public class CollectionWithEvents : CollectionBase
  {
    // Declare the event signatures
    public delegate void CollectionClear();
    public delegate void CollectionChange(int index, object value);
    // Collection change events
    public event CollectionClear Clearing;
    public event CollectionClear Cleared;
    public event CollectionChange Inserting;
    public event CollectionChange Inserted;
    public event CollectionChange Removing;
    public event CollectionChange Removed;
    // Overrides for generating events
    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
{
    /// <SUMMARY>
    /// Utility for handling a collection of currencymanagers.
    /// If we add all of the currency managers to this collection, 
    /// we can easily 'SuspendBinding' or 'ResumeBinding' on all 
    ///currency managers at the same time, 
    ///when we're changing the underlying lists, 
    ///through searching or clearing, or whatever
    /// </SUMMARY>
    public class CurrencyManagerCollection : CollectionWithEvents
    {
        /// <SUMMARY>
        /// suspend bindings for all currency managers in collection
        /// </SUMMARY>
        public void SuspendBindings()
        {
            foreach (CurrencyManager cm in this)
            {
                cm.SuspendBinding() ;
            }
        }

        /// <SUMMARY>
        /// resume bindings for all currency managers in collection
        /// </SUMMARY>
        public void ResumeBindings()
        {
            foreach (CurrencyManager cm in this)
            {
                cm.ResumeBinding() ;
            }
        }

        public int Add(CurrencyManager value)
        {
            //make sure we're not trying to add the same object
            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:

// Suppose we have a 'mainClass' that 
// has a CurrencyManagerCollection class called CurrencyManagers
// this will add the currency manager for the current form/control 
// for the binding context of the 'TheDataView'
mainClass.CurrencyManagers.Add(((CurrencyManager)
          this.BindingContext[TheDataView]));
// this will add the currency manager for the current form/control 
// for the binding context of the 'TheDataTable'
mainClass.CurrencyManagers.Add(((CurrencyManager)
          this.BindingContext[TheDataTable]));
// if you already have a CurrencyManager set up, you can just add it.
// if your CurrencyManager was called 'currencyManger' then:
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() ;
//your code here that populates the DataSet
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!