Windows Forms Data Binding

One of the most powerful aspects of .NET and Windows Forms is data binding. Historically, data binding was used to bind views to data stored in databases. Some database management systems, such as Microsoft Access, have provided GUI APIs to help developers quickly bind to data.

 

This sample is taken from Chapter 6: "Windows Forms Data Binding" of the Blue Vision Title "Developing .NET Custom Controls and Designers using C#"


Data Binding Interfaces

.NET provides a standard set of interfaces related to data binding. Each of these interfaces is described below.

IList

Any class that implements IList must support a list of homogenous types. That is, all list items must be of the same type. The first item in the list always determines the type. Some of the base classes that implement IList include Array, ArrayList, CollectionBase, DataView, and DataViewManager.

Typed IList

Similar to IList, the list must be of homogenous types. However, classes of this type can only be data bound at runtime.

IList and IComponent

When a class implements both IList and IComponent, the class can be data bound at design time. When dragging the component from the toolbox to a form, you will notice that the component appears in the component tray, like a DataSet and DataAdapter.

IListSource

This interface allows an object to "act" like a list for data binding purposes. The implemented object is not an instance of IList, but it should be able to provide one. The DataSet and DataTable objects both implement this interface. IListSource provides a single property and a single method which are described below:

ContainsListCollection: Indicates whether the collection is a collection of IList objects. For the DataSet implementation, this property returns true, because the DataSet contains a collection of collections. For the DataTable implementation, this property returns false, because the DataTable contains a collection of objects. In simple terms, implement this property to indicate how deep to go for returning a bindable list.

GetList: Returns the IList that will be data-bound. The DataSet uses this property to return a DataViewManager. The DataTable uses this property to return a DataView.

ITypedList

This interface allows an object to expose its items' properties. This interface is useful in situations where the public properties of the object should be different than the properties available for data binding. This interface is also necessary during complex binding when a list is empty but you still need to know the properties of the list item. (Remember, IList alone uses the data type of the first item in the list.) This is useful when columns headers should be created for empty lists.

IBindingList

This interface offers change notification when the list and list items have changed. There is one property, SupportsChangeNotification, which determines whether this interfaces ListChanged event will be raised. The ListChangedEventArgs contains a ListChangedType property for describing the type of change that occurred. The available ListChangedType values are as follows:

ItemAdded: An item has been added to the list. The index of the new item is the value of ListChangedEventArgs.NewIndex.

ItemChanged: An item in the list has been changed. The index of the changed item is the value of ListChangedEventArgs.NewIndex

ItemDeleted: An item has been removed from the list. The index of the deleted item is the value of ListChangedEventArgs.NewIndex.

ItemMoved: An item has been moved to another location within the list. The previous index is the value of ListChangedEv.entArgs.OldIndex. The new index is the value of ListChangedEventArgs.NewIndex.

PropertyDescriptorAdded: A PropertyDescriptor has been added.

PropertyDescriptorChanged: A PropertyDescriptor has been changed.

PropertyDescriptorDeleted: A PropertyDescriptor has been deleted.

Reset: The list has a lot of changes and controls should refresh themselves.

IEditableObject

This interface supports transaction-like operations. It allows objects to specify when changes should be made permanent. Hence, it allows changes to be rolled back. The DataGrid is one control that opts to call methods of this interface. The following methods are defined in this interface:

BeginEdit: Signals that an edit operation has started. Any changes to the object should be temporarily stored after this method has been called. When implementing this method, be sure that back-to-back calls are non-destructive. That is, the method itself should not create any changes to any temporary objects.

CancelEdit: Cancels any changes made after the BeginEdit call. In other words, all temporary objects can be destroyed when this method is called.

EndEdit: Commits any changes made after the BeginEdit call. Once this method is called, changes cannot and should not be rolled back.

The following example illustrates IEditableObject with an implantation of a Customer object.

public class Customer : IEditableObject

{

private bool _transactionStarted = false;

private String _firstName, _originalFirstName;

private String _lastName, _originalLastName;

private String _phoneNumber, _originalPhoneNumber;

public String FirstName

  {

      get

      {

            return _firstName;

      }

      set

      {

            _firstName = value;

      }

  }

public String LastName

  {

      get

      {

            return _lastName;

      }

     set

      {

            _lastName = value;

      }

  }

public String PhoneNumber

  {

      get

      {

            return _phoneNumber;

      }

      set

      {

            _phoneNumber = value;

      }

  }

  void IEditableObject.BeginEdit()

  {

      if (!_transactionStarted)

      {

            _transactionStarted = true;

            _originalFirstName = _firstName;

            _originalLastName = _lastName;

            _originalPhoneNumber = _phoneNumber;

      }

  }

  void IEditableObject.CancelEdit()

  {

      if (_transactionStarted)

      {

            _transactionStarted = false;

            _firstName = _originalFirstName;

            _lastName = _originalLastName;

            _phoneNumber = _originalPhoneNumber;

      }

  }

  void IEditableObject.EndEdit()

  {

      if (_transactionStarted)

      {

            _transactionStarted = false;

           _originalFirstName = "";

            _originalLastName = "";

            _originalPhoneNumber = "";

      }

  }

}

Comments

Be the first to write a comment

You must me logged in to write a comment.