Wiązanie danych z kontrolkami w WinForms

Żródłem danych będzie obiekt klasy Pierwiastki. Jej zadaniem jest wyznaczenie pierwiastków równania kwadratowego Klasa jest zaprojektowana tak, aby jakakolwiek zmiana właściwości A, B, C wyzwalała przeliczenie wyniku poprzez wykonanie metody Oblicz(). W metodzie Oblicz() znajduje się także wywołanie metody WyznaczPrezentacjeWyniku(), która tworzy wygodną do wyświetlenia postać wyniku.

  public class Pierwiastki : INotifyPropertyChanged
  {
    private double a;
    public double A
    {
      get { return a; }
      set { if (a != value) { a = value; Oblicz(); Powiadom("A"); } }
    }

    private double b;
    public double B
    {
      get { return b; }
      set { if (b != value) { b = value; Oblicz(); Powiadom("B"); } }
    }


    private double c;
    public double C
    {
      get { return c; }
      set { if (c != value) { c = value; Oblicz(); Powiadom("C"); } }
    }


    public double[] wynik { get; private set; }


    private void Oblicz()
    {
      double delta = b * b - 4 * a * c;
      if (delta < 0)
      {
        wynik = new double[0];
      }
      else if (delta == 0)
      {
        wynik = new double[1];
        wynik[0] = -b / (2 * a);
      }
      else
      {
        wynik = new double[2];
        wynik[0] = (-b - Math.Sqrt(delta)) / (2 * a);
        wynik[1] = (-b + Math.Sqrt(delta)) / (2 * a);
      }
      WyznaczPrezentacjeWyniku();
    }


    private void WyznaczPrezentacjeWyniku()
    {
      if (wynik.Length == 0)
        s = "Brak rozwiązań!";
      else if (wynik.Length == 1)
        s = string.Format("x0={0}", wynik[0]);
      else
        s = string.Format("x1={0}\r\nx2={1}", wynik[0], wynik[1]);
    }

    private string s;
    public string S { get { return s; } }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    void Powiadom(string NazwaWlasciwosci)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(NazwaWlasciwosci));
    }
  }

Implementacja interfejsu INotifyPropertyChanged nie jest konieczna o ile nie będzie zachodzić modyfikacja właściwości A, B, C w tle (tzn. bez pośrednictwa związych z właściwościami kontrolek).

W klasie formularza aplikacji zamieszczona jest deklaracja obiektu klasy Pierwiastki, który jest tworzony podczas działania konstruktora formularza. Również w konstruktorze formularza wykonywane jest samo wiązanie. Właściwości prw.A, prw.B, prw.C wiązane są z odpowiednimi kontrolkami klasy TextBox, zaś właściwość prw.S z kontrolką Label.

  public partial class Form1 : Form
  {
    Pierwiastki prw;

    public Form1()
    {
      InitializeComponent();

      prw = new Pierwiastki();

      Binding ba = new Binding("Text", prw, "A", false, DataSourceUpdateMode.OnPropertyChanged);
      textBox1.DataBindings.Add(ba);

      Binding bb = new Binding("Text", prw, "B", false, DataSourceUpdateMode.OnPropertyChanged);
      textBox2.DataBindings.Add(bb);

      Binding bc = new Binding("Text", prw, "C", false, DataSourceUpdateMode.OnPropertyChanged);
      textBox3.DataBindings.Add(bc);

      Binding bw = new Binding("Text", prw, "S", false, DataSourceUpdateMode.OnPropertyChanged);
      label1.DataBindings.Add(bw);
    }   
	
	
	
    private void button1_Click(object sender, EventArgs e)
    {
      prw.A = 123;
    }    
  }        

Metoda button1_Click() jest przykładem modyfikacji właściwości w tle i wizualizuje poprawną reakcję aplikacji dzięki implementacji interfejsu INotifyPropertyChanged.