N:M Beziehungen über DataGridViews anzeigen  
Frank Dzaebel, erstellt am: 26.4.2009, zuletzt geändert:  26.4.2009
Kategorie: DataGridView, .NET-Version: 3.5, [Download]

Dieser Artikel erläutert zwei Möglichkeiten zur Visualisierung von N:M Beziehungen mit dem DataGridView. Es wird eine Technik über eine Zwischentabelle mit zwei 1:N Beziehungen erläutert. Zum einen wird eine Möglichkeit über LINQ-Joins dargestellt, zum anderen über die Filter-Eigenschaft des BindingSource.
- Handling 1 (über LINQ Query)
- Handling 2 (über BindingSource.Filter-Eigenschaft)





N:M Darstellung und Handling 1 (über LINQ-Query)

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

namespace NzuM
{
  public partial class MzuN_Handling1 : Form
  {
    public MzuN_Handling1()
    {
      InitializeComponent();
    }

    // N:M Darstellung und Handling 1 (über LINQ-Query)     
    // Schritte, die zur Erstellung des Projektes geführt haben:
    //
    // 1) Über Menü "Datenquellen anzeigen" die Personal-Tabelle in die Form ziehen.
    // 2) Rechts daneben ein DataGridView einfügen und 'dgv' nennen.
    // 3) Die Kunden-Tabellen (ausserhalb eines DataGridViews) hineinziehen
    //    und mit [Entf] Taste löschen. Das gleiche mit Bestellungen.
    // 4) Den unten stehenden Quellcode einfügen.
    //
    // Für das "MzuN_Handling 1" in Program.cs bitte folgendes ersetzen:  
    // Application.Run(new MzuN_Handling1());

    private void Form1_Load(object sender, EventArgs e)
    {
      // vom Designer automatisch angelegt:
      this.kundenTableAdapter.Fill(this.personalBestellungKundeDataSet.Kunden);
      this.bestellungenTableAdapter.Fill(this.personalBestellungKundeDataSet.Bestellungen);
      this.personalTableAdapter.Fill(this.personalBestellungKundeDataSet.Personal);

      // zugefügt:
      CreateBindingHandler(personalBindingSource);
    }

    /// <param name="dataGridView">Der BindingSource,
    /// auf dessen Änderungen reagiert werden soll.</param>
    private void CreateBindingHandler(BindingSource bs)
    {
      bs.CurrentChanged +=new EventHandler(RefreshBinding);
      bs.BindingComplete += new BindingCompleteEventHandler(RefreshBinding);
      bs.ListChanged +=new ListChangedEventHandler(RefreshBinding);
      RefreshQuery();
    }

    void RefreshBinding(object sender, EventArgs e)
    {
      RefreshQuery();
    }

    private void RefreshQuery()
    {
      DataRowView drv = personalBindingSource.Current as DataRowView;
      PersonalBestellungKundeDataSet.PersonalRow pRow =
        drv.Row as PersonalBestellungKundeDataSet.PersonalRow;

      var query =
        from p in personalBestellungKundeDataSet.Personal
        where p._Personal_Nr == pRow._Personal_Nr
        join b in personalBestellungKundeDataSet.Bestellungen
          on p._Personal_Nr equals b._Personal_Nr
        join k in personalBestellungKundeDataSet.Kunden
          on b._Kunden_Code equals k._Kunden_Code
        select new
        {
          // hier halt beliebig, das, was gewünscht ist:
          NeuerName = p.Nachname + ", " + p.Vorname,
          Versanddatum = b.Straße,
          Kontaktperson = k.Kontaktperson
        };

      dgv.DataSource = query.ToList();
      var ds = query.ToList();
    }

    // automatisch von Designer angelegt.
    private void personalBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
      this.Validate();
      this.personalBindingSource.EndEdit();
      this.tableAdapterManager.UpdateAll(this.personalBestellungKundeDataSet);
    }
  }
}

N:M Darstellung und Handling 2 (über Filter-Eigenschaft)

using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using BestellRow = NzuM.PersonalBestellungKundeDataSet.BestellungenRow;

namespace NzuM
{
  public partial class MzuN_Handling2 : Form
  {
    public MzuN_Handling2()
    {
      InitializeComponent();
    }

    // N:M Darstellung und Handling 2(über Filter-Eigenschaft)
    // Schritte, die zur Erstellung des Projektes geführt haben:
    //
    // 1) Über Menü "Datenquellen anzeigen" die Personal-Tabelle in die Form ziehen.
    // 2) Rechts daneben ein DataGridView einfügen und 'dgv' nennen.
    // 3) Die Kunden-Tabellen (ausserhalb eines DataGridViews) hineinziehen
    //    und mit [Entf] Taste löschen. Das gleiche mit Bestellungen.
    // 4) Die Sub-Tabelle Bestellungen aus den Datenquellen in die Form ziehen
    //    und mit [Entf] wieder löschen, den bestellungenBindingSource in 
    //    personalBestellungenBindingSource umbenennen. 
    // 4) Den unten stehenden Quellcode einfügen.
    //
    // Für das "MzuN_Handling 2" in Program.cs bitte folgendes ersetzen:
    // Application.Run(new MzuN_Handling2());

    private void MzuN_Handling2_Load(object sender, EventArgs e)
    {
      this.kundenTableAdapter.Fill(this.personalBestellungKundeDataSet.Kunden);
      this.bestellungenTableAdapter.Fill(this.personalBestellungKundeDataSet.Bestellungen);
      this.personalTableAdapter.Fill(this.personalBestellungKundeDataSet.Personal);

      CreateBindingHandler(personalBestellungenBindingSource);
    }

    /// <summary></summary>
    /// <param name="dataGridView">Der BindingSource,
    /// auf dessen Änderungen reagiert werden soll.</param>
    private void CreateBindingHandler(BindingSource bs)
    {
      bs.CurrentChanged += new EventHandler(RefreshBinding);
      bs.BindingComplete += new BindingCompleteEventHandler(RefreshBinding);
      bs.ListChanged += new ListChangedEventHandler(RefreshBinding);
      RefreshQuery();
    }

    void RefreshBinding(object sender, EventArgs e)
    {
      RefreshQuery();
    }

    private void RefreshQuery() 
    {
      BindingSource bs = personalBestellungenBindingSource;
      StringBuilder filter = new StringBuilder();
      foreach (DataRowView drv in bs.List)
      {
        BestellRow bestellRow = drv.Row as BestellRow;
        if (filter.Length != 0) filter.Append(" OR ");
        filter.Append("[Kunden-Code] = '" + bestellRow._Kunden_Code + "'");
      }
      kundenBindingSource.Filter = filter.ToString();
      dgv.DataSource = kundenBindingSource;
      dgv.TopLeftHeaderCell.Value = kundenBindingSource.Count.ToString();
    }

    // automatisch von Designer angelegt.
    private void personalBindingNavigatorSaveItem_Click(object sender, EventArgs e)
    {
      this.Validate();
      this.personalBindingSource.EndEdit();
      this.tableAdapterManager.UpdateAll(this.personalBestellungKundeDataSet);
    }
  }
}