Laden...

DataGridView als array erstellen

Erstellt von JaquesLudwig vor 2 Jahren Letzter Beitrag vor 2 Jahren 352 Views
J
JaquesLudwig Themenstarter:in
9 Beiträge seit 2022
vor 2 Jahren
DataGridView als array erstellen

Hallo,

ich bin gerade dabei eine Excel-Datei mit mehreren Arbeitsblättern in ein C# Programm einzulesen. Dabei sollen die jeweiligen Blätter in ein TabControl - deren TabPages nach den Namen der Arbeitsblätter benannt werden - eingefügt werden. In den TabPages wird vorher ein DataGridView erstellt und die Daten der Arbeitsblätter eingefügt.

Nun dachte ich, nachdem ich vorher nicht weiß, wie viele Arbeitsblätter die einzulesende Excel-Datei hat, ich arbeite mit dynamischen Elementen.

Das Anlegen der TabPages funktioniert wunderbar und kann mit über


tabCoTabellen.TabPages[i] 

angesprochen werden.
Bei den DataGridView habe ich so meine Probleme. Kann ich denn überhaupt ein DataGridView als array erstellen? Wenn ja, wie muss ich das machen?
Momentan erstelle ich mein DataGridView so.


DataGridView dgv = new DataGridView();

und füge es dann in die TabControl bzw. die jeweilige Page ein:


dgv.Name = title;
dgv.DataSource = dt;
dgv.Dock = DockStyle.Fill;
tabCoTabellen.TabPages[i].Controls.Add(dgv);

Nun habe ich meistens mehrere DataGridView, denen ich ja nicht alle den Namen "dgv" geben kann. Ich dachte da an


dgv[i]

, bekomme das aber nicht hin. Die Daten aus der Excel Tabelle sollen später noch bearbeitet werden, also müsste ich die jeweiligen DataGridView ansprechen, wird aber schwierig, wenn die alle den gleichen Namen haben.

Vielen Dank schon mal für die Hilfe.

Grüße,

Jaques-Ludwig

4.931 Beiträge seit 2008
vor 2 Jahren

Hallo und willkommen,

Arrays und Listen gehören zu den Grundlagen von C# (bzw. fast jeder Programmiersprache), bevor man Anwendungsprogramme erstellt:


DataGridView[] dgvs = new DataGridView[X];
// und dann in einer Schleife
{
   var dgv = new DataGridView();
   dgvs[i] = dgv;
}
// bzw. hier besser
List<DataGridView> dgvs = new List<DataGridView>();
// ebenfalls in einer Schleife
{
  var dgv = new DataGridView();
  dgvs.Add(dgv));
}

Aber ich denke, das wußtest du eigentlich schon, aber insbesondere für dynamische Controls gibt es auch den FAQ-Beitrag: [FAQ] Variablennamen zur Laufzeit zusammensetzen / Dynamisches Erzeugen von Controls.

J
JaquesLudwig Themenstarter:in
9 Beiträge seit 2022
vor 2 Jahren

Vielen Dank für die schnelle Antwort und die Hinweise. Ich arbeite auch gerade ein C#-Buch durch, nur geht das sehr schleppend voran und manchmal möchte ich schon mal das ein oder andere probieren, ohne bereits genügend Erfahrung gesammelt zu haben. Dann ergeben sich solche Fragen.
Was ich gestern alles gelesen und versucht habe. Ich probiere deine Lösung heute Abend mal aus.

Jaques-Ludwig

J
JaquesLudwig Themenstarter:in
9 Beiträge seit 2022
vor 2 Jahren

Hallo,

es funktioniert. Vielen Dank nochmal.

Ich hab es so gemacht:


List<DataGridView> a_dgv = new List<DataGridView> ();

a_dgv.Add(new DataGridView());
a_dgv[i].Name = title;
a_dgv[i].DataSource = dt;
a_dgv[i].Dock = DockStyle.Fill;
tabCoTabellen.TabPages[i].Controls.Add(a_dgv[i]);

Was ich noch nicht nachvollziehen kann ist folgender "Fehler":

In einer Schleife gehe ich sämtliche DataGridViews durch


for (int i = 0; i < Anz_Tabellen; i++)
            {
                //tabCoTabellen.SelectedIndex = i;
                int Test_Anzahl = a_dgv[i].RowCount; 
                String Test_Name = a_dgv[i].Name;

            }

In der Variablen Test_Name wird mir der korrekte Name des jeweiligen DataGridView angezeigt. Allerdings bekomme ich bei der Variablen Test_Anzahl nur dann die genaue Anzahl der Zeilen, wenn ich vorher in der TabControl die zur DataGridView dazugehörige TabPage selektiert habe. Warum muss ich beim Abfragen der Anzahl der Zeilen die passende TabPage selektiert haben, bei der Abfrage des Namens aber nicht?

4.931 Beiträge seit 2008
vor 2 Jahren

Der Name ist ja einfach nur ein String, den du einmalig setzt, während die Rows (und der RowCount) dynamisch anhand der DataSource erstellt werden (und diese eben erst intern erzeugt werden, wenn das DataGridView angezeigt wird).

PS:


var dgv = new DataGridView();
dgv.Name = title;
dgv.DataSource = dt;
dgv.Dock = DockStyle.Fill;
a_dgv.Add(dgv);

ist besser (und performanter), als jedesmal das Element über das Array anhand des Index anzusprechen.

F
10.010 Beiträge seit 2004
vor 2 Jahren

Auch dürfte das größte Problem eher sein, das Du die Daten in den UI Elementen suchst.

Statt dir die DGV zu merken, merke dir die DataTables ( auch so ein veraltetes Konstrukt ) und arbeite mit denen, nicht mit dem UI Control

J
JaquesLudwig Themenstarter:in
9 Beiträge seit 2022
vor 2 Jahren

Auch dürfte das größte Problem eher sein, das Du die Daten in den UI Elementen suchst.

Statt dir die DGV zu merken, merke dir die DataTables ( auch so ein veraltetes Konstrukt ) und arbeite mit denen, nicht mit dem UI Control

Sorry für die Nachfrage, aber das verstehe ich nicht. Ist das auf meinen Code in der Schleife bezogen? Also den:


for (int i = 0; i < Anz_Tabellen; i++)
            {
                //tabCoTabellen.SelectedIndex = i;
                int Test_Anzahl = a_dgv[i].RowCount;
                String Test_Name = a_dgv[i].Name;

            }

Wenn ja, wie sollte ich das besser machen? Die DGV sind in einem TabControl eingebettet. Die heißt bei mir tabCoTabellen.TabPages_.

Danke

4.931 Beiträge seit 2008
vor 2 Jahren

Was FZelle meint, ist, daß du zwischen UI und Daten (Logik) unterscheiden mußt.
Nur wenn du kosmetische Änderungen (Layout, Design) durchführen willst, solltest du die UI-Controls ansprechen, ansonsten solltest du datenorientiert denken (und programmieren).

Mittels


dgv.DataSource = dt;

hast du die Datatable dt an das DataGridView gebunden und solltest daher direkt Änderungen an der DataTable durchführen. Merke dir daher (zusätzlich) diese in einem Array (bzw. Liste) und arbeite nur mit diesen (so hast du dann auch nicht mehr das Problem bzgl. der Selektion der TabPage).
Lege am besten eine eigene (Logik-)Klasse für die Datenänderungen an (s.a. [Artikel] Drei-Schichten-Architektur).

J
JaquesLudwig Themenstarter:in
9 Beiträge seit 2022
vor 2 Jahren

Für mich zum Verständnis:


List<DataGridView> a_dgv = new List<DataGridView> ();

for (int i = 0; i < Anz_Tabellen; i++)
{
   string title = cboSheet.Items[i].ToString();
   tabCoTabellen.TabPages.Add(title);
   chkLiSheets.Items.Add(title);

   DataTable dt = dataTableCollection[cboSheet.Items[i].ToString()];
   var dgv = new DataGridView();
   dgv.Name = title; 
   dgv.DataSource = dt;
   dgv.Dock = DockStyle.Fill;
   a_dgv.Add(dgv);
   tabCoTabellen.TabPages[i].Controls.Add(a_dgv[i]);
 }

Ich erstelle innerhalb einer Schleife mehrere DataGridView immer mit selben Namen (dgv), denen ich eine Datatable mit immer dem selben Namen "dt", aber unterschiedlichem Inhalt zuweise:

Anschließend habe ich diese DataGridView einer Liste DataGridViews "a_dgv" hinzugefügt und vorher natürlich diese Liste erstellt:

Aber jede so erstellte DataGridView und damit natürlich auch die DataGridViews in der Liste (a_dgv) haben doch die gleiche DataSource, nämlich dt. Wenn ich jetzt direkte Veränderung an der Datatable dt machen würde, würde das ja nur die letzte Datatable betreffen, die ich erstellt habe. Deswegen macht es für mich keinen Sinn an "dt" Veränderungen vorzunehmen. Sehe ich das richtig so?

Jetzt habe ich verstanden, dass ich die jeweilige dt in eine Liste/Array schreiben soll, um damit zu arbeiten und nicht immer aus dem DataGridView rauszulesen und dann zu ändern. Ich kann nirgends etwas finden, wie ich einfach ein DataTable in eine Liste speichern kann. Das scheint mit einer einfachen Anweisung nicht zu gehen. Zumindest finde ich im Netz nur Vorgehensweisen, die mir noch zu schwierig sind. Sollte das der Fall sein, muss ich halt erst noch Erfahrungen sammeln. Sollte es einen einfachen Weg geben, bin ich für jeden Tipp dankbar.

Ich nehme an, bei Änderungen in diesen Listen/Array, in die ich meine DataTables speichern soll, müsste ich bei erfolgter Änderung wieder der entsprechenden DataGridView in meiner Liste "a_dgv" als DataSource zuordnen? Ist das richtig?

Vielen Dank für euere Tipps und euere Geduld mit mir.

Jaques-Ludwig

4.931 Beiträge seit 2008
vor 2 Jahren

Du hast ja schon ein DataTable-Array: dataTableCollection

Und dann kannst du direkt damit arbeiten (anstatt über das zugehörige UI-Control auf die Daten zuzugreifen).

Nur noch mal als Erklärung:
Ich dachte, du hättest jeweils in der Schleife ein neues DataTable-Objekt angelegt und der DataGridView.DataSource zugewiesen.
In deinem Code ist dt ja nur eine Referenz auf die in der dataTableCollection enthaltene DataTable und du könntest auch gleich


dgv.DataSource = dataTableCollection[cboSheet.Items[i].ToString()]

schreiben (solange du in der Schleife nicht auch noch anderweitig auf diese DataTable zugreifst - denn nur dann macht es Sinn, eine eigene Variable (Referenz) zu benutzen, um nicht jedesmal auf die Collection zuzugreifen).

Hättest du nicht schon diese dataTableCollection, so würdest du analog zur List<DataGridView> genauso eine Liste für die DataTable-Objekte benutzen:


List<DataTable> dataTables = new List<DataTable>();

// in Schleife
var dt = new DataTable();
// dt-Zuweisungen...
dataTables.Add(dt);