Поделиться через


Практическое руководство. Получение уведомления об изменении данных с использованием компонента BindingSource и интерфейса INotifyPropertyChanged

Компонент BindingSource автоматически обнаруживает изменения в источнике данных, когда тип, содержащийся в этом источнике, реализует интерфейс INotifyPropertyChanged и вызывает события PropertyChanged при изменении значения свойства. Это очень удобно, поскольку элементы управления, связанные с компонентом BindingSource, будут автоматически обновляться при изменении значений источника данных.

Примечание

Если источник данных реализует INotifyPropertyChanged и выполняется асинхронная операция, не следует вносить изменения в источник данных в фоновом потоке.Вместо этого необходимо прочитать данные в фоновом потоке и внедрить их в список в потоке пользовательского интерфейса.

Пример

В следующем примере кода демонстрируется простая реализация интерфейса INotifyPropertyChanged. Также в этом примере показано, как компонент BindingSource автоматически передает изменение источника данных элементу управления, когда компонент BindingSource привязан к списку типа INotifyPropertyChanged.

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Diagnostics
Imports System.Drawing
Imports System.Data.SqlClient
Imports 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
    Inherits System.Windows.Forms.Form
    ' This button causes the value of a list element to be changed.
    Private changeItemBtn As New Button()

    ' This DataGridView control displays the contents of the list.
    Private customersDataGridView As New DataGridView()

    ' This BindingSource binds the list to the DataGridView control.
    Private customersBindingSource As New BindingSource()

    Public Sub New()
        ' Set up the "Change Item" button.
        Me.changeItemBtn.Text = "Change Item"
        Me.changeItemBtn.Dock = DockStyle.Bottom
        AddHandler Me.changeItemBtn.Click, AddressOf changeItemBtn_Click
        Me.Controls.Add(Me.changeItemBtn)

        ' Set up the DataGridView.
        customersDataGridView.Dock = DockStyle.Top
        Me.Controls.Add(customersDataGridView)

        Me.Size = New Size(800, 200)
        AddHandler Me.Load, AddressOf Form1_Load

    End Sub 'New

    Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Me.Load

        ' Create and populate the list of DemoCustomer objects
        ' which will supply data to the DataGridView.
        Dim customerList As New BindingList(Of DemoCustomer)

        customerList.Add(DemoCustomer.CreateNewCustomer())
        customerList.Add(DemoCustomer.CreateNewCustomer())
        customerList.Add(DemoCustomer.CreateNewCustomer())

        ' Bind the list to the BindingSource.
        Me.customersBindingSource.DataSource = customerList

        ' Attach the BindingSource to the DataGridView.
        Me.customersDataGridView.DataSource = Me.customersBindingSource

    End Sub 'Form1_Load

    ' This event handler changes the value of the CompanyName
    ' property for the first item in the list.
    Private Sub changeItemBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
        ' Get a reference to the list from the BindingSource.
        Dim customerList As BindingList(Of DemoCustomer) = _
            CType(customersBindingSource.DataSource, BindingList(Of DemoCustomer))

        ' Change the value of the CompanyName property for the 
        ' first item in the list.
        customerList(0).CustomerName = "Tailspin Toys"

    End Sub



    <STAThread()> _
    Shared Sub Main()
        Application.EnableVisualStyles()
        Application.Run(New Form1())

    End Sub
End Class

' This class implements a simple customer type 
' that implements the IPropertyChange interface.

Public Class DemoCustomer
    Implements INotifyPropertyChanged

    ' These fields hold the values for the public properties.
    Private idValue As Guid = Guid.NewGuid()
    Private customerNameValue As String = String.Empty
    Private phoneNumberValue As String = String.Empty

    Public Event PropertyChanged As PropertyChangedEventHandler _
        Implements INotifyPropertyChanged.PropertyChanged

    Private Sub NotifyPropertyChanged(ByVal info As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    End Sub

    ' The constructor is private to enforce the factory pattern.
    Private Sub New()
        customerNameValue = "Customer"
        phoneNumberValue = "(555)555-5555"

    End Sub

    ' This is the public factory method.
    Public Shared Function CreateNewCustomer() As DemoCustomer
        Return New DemoCustomer()

    End Function

    ' This property represents an ID, suitable
    ' for use as a primary key in a database.
    Public ReadOnly Property ID() As Guid
        Get
            Return Me.idValue
        End Get
    End Property


    Public Property CustomerName() As String
        Get
            Return Me.customerNameValue
        End Get

        Set(ByVal value As String)
            If Not (value = customerNameValue) Then
                Me.customerNameValue = value
                NotifyPropertyChanged("CustomerName")
            End If
        End Set
    End Property


    Public Property PhoneNumber() As String
        Get
            Return Me.phoneNumberValue
        End Get

        Set(ByVal value As String)
            If Not (value = phoneNumberValue) Then
                Me.phoneNumberValue = value
                NotifyPropertyChanged("PhoneNumber")
            End If

        End Set
    End Property
End Class
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";
    }

    [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");
            }
        }
    }
}

Компиляция кода

Для этого примера необходимы следующие условия.

  • Ссылки на сборки System, System.Data, System.Drawing и System.Windows.Forms.

Дополнительные сведения о построении этого примера из командной строки для Visual Basic или Visual C# см. в разделе Построение из командной строки (Visual Basic) или Построение из командной строки с помощью csc.exe. Можно также построить этот пример в Visual Studio путем вставки кода в новый проект. Дополнительные сведения см. в следующем разделе. Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio.

См. также

Задачи

Практическое руководство. Уведомление об изменении данных с использованием метода ResetItem компонента BindingSource

Ссылки

INotifyPropertyChanged

Другие ресурсы

Компонент BindingSource