Wie Sub-Klassen über CurrentItemChanged informieren  
Frank Dzaebel, erstellt am: 21.1.2008, zuletzt geändert:  21.1.2008
Kategorie: Datenbindung, .NET-Version: 2.0/3.5, [Download]

OO-Design, wie Subklassen bei der Datenbindung ihre Eltern-Klassen informieren können (CurrentItemChanged), damit diese (zum Beispiel) ihre Ansicht aktualisieren können. Ein typisches Mittel ist die INotifyPropertyChanged-Schnittstelle. Spart man sich diese Schnittstelle, ist ggf. ein  ResetCurrentItem als Workaround möglich. 


using System;
using System.Data;
using System.ComponentModel;
using System.Windows.Forms;
using System.Diagnostics;

namespace BindingListChanged
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    BindingList<Person> personen = new BindingList<Person>();
    BindingSource bs;

    private void Form1_Load(object sender, EventArgs e)
    {
      FülleDaten(personen);
      bs = new BindingSource();
      bs.DataSource = personen; dgv.DataSource = bs;
      bs.CurrentItemChanged +=new EventHandler(bs_CurrentItemChanged);
      dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
      dgv.Columns["PrivatAnschrift"].ReadOnly = true;
      textBox1.DataBindings.Add("Text", bs, "Name");
      textBox2.DataBindings.Add("Text", bs, "Alter");
      textBox3.DataBindings.Add("Text", bs, "PrivatAnschrift.Strasse");
      foreach (Control tb in tlPanel1.Controls)
        if (tb is TextBox)
          tb.TextChanged += new EventHandler(tb_TextChanged);
    }

    int counter = 0;
    void tb_TextChanged(object sender, EventArgs e)
    {
      ZeigeEreignis("TextChanged");
      if (MitResetCurrentItem())
        bs.ResetCurrentItem(); // <<-- Workaround, wenn ohne INotifyPropertyChanged
} private bool MitResetCurrentItem() { return !chkReset.Checked; } void bs_CurrentItemChanged(object sender, EventArgs e) { ZeigeEreignis("CurrentItemChanged"); } private void ZeigeEreignis(string ereignis) { txtInfos.AppendText(String.Format("{0}:{1}\r\n", counter++,ereignis)); txtInfos.ScrollToCaret(); } private void FülleDaten(BindingList<Person> personen) { personen.Add(new Person(42, "Alpha", new Anschrift("A Strasse 1"))); personen.Add(new Person(21, "Beta", new Anschrift("B Strasse 2"))); personen.Add(new Person(53, "Gamma", new Anschrift("G Strasse 3"))); personen.Add(new Person(19, "Delta", new Anschrift("D Strasse 4"))); } class Person : INotifyPropertyChanged { public Person(int alter, string Name, Anschrift privatAnschrift) { this.Alter = alter; this.name = Name; this.privatAnschrift = privatAnschrift; this.privatAnschrift.PropertyChanged += new PropertyChangedEventHandler(privatAnschrift_PropertyChanged); } void privatAnschrift_PropertyChanged(object sender, PropertyChangedEventArgs e) { NotifyPropertyChanged("PrivatAnschrift"); } private int alter; public int Alter { get { return alter; } set { alter = value; } } private string name; public string Name { get { return name; } set { name = value; } } private Anschrift privatAnschrift; public Anschrift PrivatAnschrift { get { return privatAnschrift; } set { privatAnschrift = value; NotifyPropertyChanged("PrivatAnschrift"); } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(info)); } } class Anschrift : INotifyPropertyChanged { public Anschrift(string strasse) { this.strasse = strasse; } private string strasse; public string Strasse { get { return strasse; } set { strasse = value; NotifyPropertyChanged("Strasse"); } } public override string ToString() { return strasse; } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(info)); } } private void chkReset_CheckedChanged(object sender, EventArgs e) { chkReset.Text = (chkReset.Checked ? "Ohne" : "Mit") + " ResetCurrentItem"; } } }