How to: Raise Change Notifications Using a BindingSource and the INotifyPropertyChanged Interface
The BindingSource component will automatically detect changes in a data source when the type contained in the data source implements the INotifyPropertyChanged interface and raises PropertyChanged events when a property value is changed. This is useful because controls bound to the BindingSource will then automatically update as the data source values change.
Note: |
|---|
If your data source implements INotifyPropertyChanged and you are performing asynchronous operations, you should not make changes to the data source on a background thread. Instead, you should read the data on a background thread and merge the data into a list on the UI thread. |
The following code example demonstrates a simple implementation of the INotifyPropertyChanged interface. It also shows how the BindingSource automatically passes a data source change to a bound control when the BindingSource is bound to a list of the INotifyPropertyChanged type.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Diagnostics; using System.Drawing; using System.Data.SqlClient; using System.Windows.Forms; // This form demonstrates using a BindingSource to bind // a list to a DataGridView control. The list does not // raise change notifications, however the DemoCustomer type // in the list does. public class Form1 : System.Windows.Forms.Form { // This button causes the value of a list element to be changed. private Button changeItemBtn = new Button(); // This DataGridView control displays the contents of the list. private DataGridView customersDataGridView = new DataGridView(); // This BindingSource binds the list to the DataGridView control. private BindingSource customersBindingSource = new BindingSource(); public Form1() { // Set up the "Change Item" button. this.changeItemBtn.Text = "Change Item"; this.changeItemBtn.Dock = DockStyle.Bottom; this.changeItemBtn.Click += new EventHandler(changeItemBtn_Click); this.Controls.Add(this.changeItemBtn); // Set up the DataGridView. customersDataGridView.Dock = DockStyle.Top; this.Controls.Add(customersDataGridView); this.Size = new Size(800, 200); this.Load += new EventHandler(Form1_Load); } private void Form1_Load(System.Object sender, System.EventArgs e) { // Create and populate the list of DemoCustomer objects // which will supply data to the DataGridView. BindingList<DemoCustomer> customerList = new BindingList<DemoCustomer>(); customerList.Add(DemoCustomer.CreateNewCustomer()); customerList.Add(DemoCustomer.CreateNewCustomer()); customerList.Add(DemoCustomer.CreateNewCustomer()); // Bind the list to the BindingSource. this.customersBindingSource.DataSource = customerList; // Attach the BindingSource to the DataGridView. this.customersDataGridView.DataSource = this.customersBindingSource; } // Change the value of the CompanyName property for the first // item in the list when the "Change Item" button is clicked. void changeItemBtn_Click(object sender, EventArgs e) { // Get a reference to the list from the BindingSource. BindingList<DemoCustomer> customerList = this.customersBindingSource.DataSource as BindingList<DemoCustomer>; // Change the value of the CompanyName property for the // first item in the list. customerList[0].CustomerName = "Tailspin Toys"; customersBindingSource.ResetItem(0); } [STAThread] static void Main() { Application.EnableVisualStyles(); Application.Run(new Form1()); } } // This is a simple customer class that // implements the IPropertyChange interface. public class DemoCustomer : INotifyPropertyChanged { // These fields hold the values for the public properties. private Guid idValue = Guid.NewGuid(); private string customerNameValue = String.Empty; private string phoneNumberValue = String.Empty; public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } // The constructor is private to enforce the factory pattern. private DemoCustomer() { customerNameValue = "Customer"; phoneNumberValue = "(555)555-5555"; } // This is the public factory method. public static DemoCustomer CreateNewCustomer() { return new DemoCustomer(); } // This property represents an ID, suitable // for use as a primary key in a database. public Guid ID { get { return this.idValue; } } public string CustomerName { get { return this.customerNameValue; } set { if (value != this.customerNameValue) { this.customerNameValue = value; NotifyPropertyChanged("CustomerName"); } } } public string PhoneNumber { get { return this.phoneNumberValue; } set { if (value != this.phoneNumberValue) { this.phoneNumberValue = value; NotifyPropertyChanged("PhoneNumber"); } } } }
This example requires:
References to the System, System.Data, System.Drawing and System.Windows.Forms assemblies.
For information about building this example from the command line for Visual Basic or Visual C#, see Building from the Command Line (Visual Basic) or Command-line Building With csc.exe. You can also build this example in Visual Studio by pasting the code into a new project.
Note: