C# Befuellen eines DataGridViews mit foreach klappt nicht

Ranayna

Vice Admiral
Registriert
Mai 2019
Beiträge
6.489
Hallo zusammen,

ich darf mal wieder meine Ignoranz zur schau stellen. Ich moechte das erste mal mit einem DataGridView arbeiten und fuchse mich da grade ein bisschen rein.
Datenquelle ist ein XML, welches ich per REST API von einem remote Server hole. Der Part funktioniert, und das habe ich auch schon des oefteren gemacht.

Jetzt stehe ich aber irgendwie total auf dem Schlauch beim Auswerten der Daten...
Folgender Code:
C#:
XmlNodeList nodeList = resultXML.SelectNodes("//row");

string[] gridRow = new string[3];

foreach (XmlNode node in nodeList)
{
    gridRow[0] = node.SelectSingleNode("//Knoten1").InnerText;
    gridRow[1] = node.SelectSingleNode("//Knoten2").InnerText;
    gridRow[2] = node.SelectSingleNode("//Knoten3").InnerText;

    dataGridView1.Rows.Add(gridRow);
}

Mein Problem: Der DataGridView wird gefuellt, aber in allen Zeilen des Views steht das gleiche, obwohl die Rohdaten dem wiedersprechen. Count passt, ich bekomme eine Zeile pro XmlNode.
Setze ich einen Breakpoint im foreach, sehe ich, das der node auch bei jedem Durchlauf anders ist, aber das gridRow Array wird nicht aktualisiert. Klicke ich mich durch die "locals" im Debugger finde ich keinen Fehler im XML, alle Nodes der nodeList sind unterschiedlich, und das "node" Element, bzw dessen innerXML passt auch bei jedem Durchlauf.
Ist egal ob ich das Array innerhalb des foreaches bei jedem durchlauf definiere oder es wie oben ausserhalb tue, das Ergebnis ist das selbe.

Beispiel XML
XML:
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
    <ns:[ENTFERNT]>
        <return>
            <row>
                <Knoten1>Text</Knoten1>
                <Knoten2>NochmehrText</Knoten2>
                <Knoten3>f</Knoten3>
            </row>
            <row>
                <Knoten1>Text</Knoten1>
                <Knoten2>AndererText</Knoten2>
                <Knoten3>t</Knoten3>
            </row>
            <row>
                <Knoten1>Text</Knoten1>
                <Knoten2>NochmalAndererText</Knoten2>
                <Knoten3>f</Knoten3>
            </row>
            [...weitere <row></row> Elemente, immer im gleichen Muster...]
        </return>
    </ns:[ENTFERNT]>
    </soapenv:Body>
</soapenv:Envelope>
Falls relevant: Die Anwendung ist eine 08/15 WinForms Anwendung, erstellt in VS2017, der Code ist Teil einer Button_Click Methode.

Wahrscheinlich ist das mal wieder eine pisselige Kleinigkeit an der man erkennt das ich keine Ahnung habe :D Bitte seit milde :)
 
Der Inhalt welches Knotens steht denn in allen Grid-Rows? Der Letzte?
Ich bin ziemlich raus aus C# aber mir ist aufgefallen, dass Du nur einmal eine Instanz von gridRow erzeugst und diese in jedem Durchlauf wieder dem Grid zuweist.
Ist die Zuweisung nur eine Referenz? Dann würde der inhalt ständig wieder überschrieben werden und am Schluss hast Du in allen Zeilen den Inhalt des zuletzt gelesenen Knotens.
 
  • Gefällt mir
Reaktionen: l0lsh4rp
Ne, ist immer der Inhalt des ersten Durchlaufs.
An sowas habe ich auch irgendwie gedacht, aber selbst wenn ich die Erstellung des Arrays in das foreach verschiebe veraendert sich das Verhalten nicht, mal abgesehen dass das nicht sehr effizient ist ;)
Das Array verwende ich auch nirgendwo anders, das will ich nur als Zwischenschritt zum Fuellen nehmen.
 
Hmmm, dann bin ich spontan überfragt.
Das war nur so mein erster Verdacht beim Lesen - wie gesagt, C# bin ich nicht mehr drin...
Sorry.
 
Ich hab mal in WPF nachgesehen, was natürlich nicht das komplett gleiche ist.
Aber wie auch schon von AgiOli erwähnt, solltest du bei dem deklarieren von gridRow außerhalb der Vorschleife tatsächlich immer die gleichen Referenzen haben.
Die Frage ist nur wieso du dann trotzdem noch das gleiche siehst.
Kannst du vielleicht noch die Deklaration der Öberfläche zeigen wo gebinded wird?
(Ich hab leider nur einigermaßen Erfahrung mit WPF, absolut keine mit WinForms)
 
@davisx2: Meinst du das Binding des DataGridViews? Da mache ich soweit ich weiss garnichts. Ich habe drei Columns definiert ueber den Editor, aber sonst nichts gemacht, die Frage ob ich Bindings einrichten will habe ich ignoriert.
Bei meinen ersten Tests damit habe ich dann schnoede hardgecodete string[] arrays ueber Rows.Add in der Form1.Load Methode dem DataGridView hinzugefuegt. Das hat funktioniert, auf auf Grundlage dieses erfolgreichen Hinzufuegens ist der Code aus meinem Snippet entstanden.
Details kann ich erst morgen nachreichen.

@lokon: Ich bin mir ziemlich sicher das der XPath so in Ordnung ist.
Schaue ich mir das ganze im Debugger an, hat jedes <row> Element immer die gleichen Subnodes, mit unterschiedlichen Inhalten. Jeder dieser Subnodes ist zudem auch wirklich nur einmal im jeweiligen <row> Node enthalten.

Mein Ziel ist am Ende einfach nur eine schlichte Visualisierung des Statuses diverser Geraete. Im GridView habe ich dann nur drei Spalten: Name, Beschreibung und Status. Und genau das steht jeweils in den drei Elementen des <row> Nodes meines XMLs.
 
Habs nochmal in WinForms testen können. @lokon hat Recht, das ist was du brauchst:
C#:
gridRow[0] = node.SelectSingleNode("./Knoten1").InnerText;
gridRow[1] = node.SelectSingleNode("./Knoten2").InnerText;
gridRow[2] = node.SelectSingleNode("./Knoten3").InnerText;

Die Arraydeklaration kann man außerhalb des foreach lassen, das ist wohl nur bei WPF anders, oder ich hab vorher was falsch gemacht :D
 
  • Gefällt mir
Reaktionen: Ranayna
Ok, das werde ich morgen mal testen.
Ich haett aber schwoeren koennen das ich schon eher einen XPath mit "//" benutzt habe, auch wenn die Struktur nur zwei Ebenen hatte. Und es erklaert meines Erachtens auch nicht, warum der erste Durchlauf der Schleife geht, die weiteren aber nicht.
 
Sie gehen alle. Das Problem ist nur: Du kriegst immer den ersten "Knoten1", "Knoten2" und "Knoten3".
Durch das "//" geht die Suche vom Anfang des Dokuments aus, statt vom aktuellen Knoten wenn ich mich richtig erinnere
 
  • Gefällt mir
Reaktionen: Ranayna
Aber ich habe doch im naechsten Durchlauf der foreach eine neue Node.
Aber ich sehe worauf du hinaus willst, er koennte evtl. in der nodeList anstatt dem node suchen?
 
Meine Einschätzungen sind folgende, hoffe jemand kann bestätigen/korrigieren:
Auch die einzelne Node hat eine Referenz auf das gesamte Dokument.
Dadurch wird praktisch von der ersten Zeile des XML-Dokuments gesucht und somit sollte die Suche bei dem "soapenv:Envelope" Element beginnen.
Da ich aber nur sehr sehr kurz mit XPath und XMLDocument gearbeitet habe, ist das nicht sicher :p
 
  • Gefällt mir
Reaktionen: Ranayna
Ich hätte ja Linq2Xml genommen aber anyway.
Der Weg über den Indizierer scheint mir jedenfalls passender:
var foo = node["Knoten1"].InnerText;
 
Verwendung von XML bei mir schon sehr lange her - schon damals musste immer der Standard gelesen und dann herumexperimentiert werden - weil zB im Standard nur wenige Beispiele sind, und zusätzlich Sprachbarrieren hinzukommen können .
davisx2 schrieb:
Auch die einzelne Node hat eine Referenz auf das gesamte Dokument.

Stackoverflow hat zB in den Antworten etwas zum Unterschied zwischen "//" und ".//" in XPath.

Außerdem ist bei @Ranayna eventuell sein "gedankliches Modell" wie die XmlNode Bearbeitung funktioniert ein anderes als es in C# / Xpath ist - die Nodes sind eben nicht "herausgelöst" und vergessen das Eltern-"Dokument" bzw. Element / XML DOM ; also ein "nodeselect" erzeugt kein neues DOM mit den Nodes als "Root" Element (1).
Das Modell mit Indizierer bzw. vermutlich auch mit einem Iterator (?) würde sich da "intuitiver" Verhalten.
Lt MS Doku benutzt zB GetElementsByTagName kein XPath
 
  • Gefällt mir
Reaktionen: Ranayna und davisx2
Verdammte Axt, @lokon und @davisx2, ihr habt recht.

Der XPath mit ./ funktioniert wie es soll.

Ja, da hatte ich tatsaechlich einen kapitalen Denkfehler wie sich einzelne nodes in einer foreach Verhalten.

Das erklaert auch etwas was mir schon vor einer Weile komisch vorkam. Ich war da in einer aehnlichen Situation, in diesem Fall war es moeglich, aber nicht wahrscheinlich, das ich mehrere gleiche Elemente in einen node habe.
Da habe ich auch mit den "//" Pfaden gearbeitet und mir nichts dabei gedacht das ich niemals mehr als einen Eintrag hatte :D
 
Zurück
Oben