hallo zusammen,
ich möchte gerne meine Datagridview tabelle in einer XML Datei speichern. Habe auch jetzt schon einiges im internet darüber gefunden, aber nichts was wirklich funktioniert. Ich möchte ausserdem, dass ich zusätzlich das Datenformat mit abspeichern kann....
in etwa diesem format soll die xml datei sein:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Data>
<Key xsi:type="xsd:string">AdapterType</Key>
<Value xsi:type="xsd:string">StepAdapter</Value>
</Data>
<Data>
<Key xsi:type="xsd:string">CheckCodeMain</Key>
<Value xsi:type="xsd:string">350</Value>
</Data>
Das Datagridview wird noch zur laufzeit editierbar sein.
vielleicht kann mir jemand helfen..
DANKE
Hm, eine GriviewToXML()-Funktion wird es wohl nicht geben, weshalb man das selbst umsetzen müsste. Aber wo genau ist denn das Problem? XmlDocument bietet eigentlich alles, was man braucht (MSDN hilft hier extrem weiter) und das GridView durchlaufen und die Daten in XmlNodes drücken ist doch schnell gemacht. Oder ist das Problem ein anderes?
Hallo bredator,
von Hand braucht man das nicht zu machen, s. meine Antwort unter C-Sharp-Forum.de - Datagridview in xml speichern.
Okay, wieder was gelernt 😄
Danke für den Hinweis, jetzt gehts ans Refactoring ^^
problem besteht immernoch 😕
daten können geladen werden, speichern funktioniert leider nicht. es werden nur die elemente aber ohne inhalt angelegt....
also so sieht meine xml bis jetzt aus:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<TableName />
<TableName />
</DocumentElement>
der code dazu:
DataGridViewRowCollection coll = dataGridView1.Rows;
DataTable t = new DataTable();
t.Columns.Add();
foreach (DataGridViewRow item in coll)
{
t.Rows.Add(item.Cells[0].Value);
t.Columns.Add(item.ToString());
}
t = (DataTable)DatenTabelle.DataSource;
dt.TableName = "TableName";
t.WriteXml("D:\\Customers.xml", System.Data.XmlWriteMode.IgnoreSchema);
Du musst den Tabellen auch Zeilen hinzufügen. Ansonsten hast du den Effekt, wie er bei dir besteht. - Warum sollte dein Programm auch unnötigen Output schreiben?
Schmarn... du füllst die Tabelle nur falsch.
Mal zum nachdenken:
DataTable dt = new DataTable();
foreach(Spalte in DataGrid)
{
dt.Colums.Add(Spaltenname);
}
foreach(Zeile in DataGrid)
{
DataRow row = dt.Rows.Add();
foreach(Spalte in dt)
{
row[Spalte] = Zeile[Spalte];
}
}
Der Code wird übrigens nicht funktionieren.
Der Pseudocode korrekt umgesetzt ergibt für meinen Test folgende Ausgabe:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<Test>
<ID>1</ID>
<Name>Paul</Name>
<Alter>21</Alter>
</Test>
<Test>
<ID>2</ID>
<Name>Werner</Name>
<Alter>23</Alter>
</Test>
<Test />
</DocumentElement>
Beachte bitte auch, das ein leeres <Test /> angibt, dass in der Zeile keine Daten vorhanden sind.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
also muss ich die zeilen und die spalten in meinem dgv durchlaufen und die werte jeweils abholen?!
DataGridViewRowCollection coll = dataGridView1.Rows;
DataGridViewColumnCollection coll2 = dataGridView1.Columns;
DataTable t = new DataTable();
t.Columns.Add();
foreach (DataGridViewRow item in coll)
{
t.Columns.Add("Column1");
}
foreach (DataGridViewColumn item in coll2)
{
DataRow row = dt.Rows.Add();
foreach(coll2 in dt) //Ab hier versteh ichs nicht mehr ganz....
{
t.Rows[1] = coll2[1]; //Wie greif ich auf die spalten zu???
}
}
t = (DataTable)DatenTabelle.DataSource;
dt.TableName = "TableName";
dt.Columns.Add("item");
t.WriteXml("D:\\Customers.xml", System.Data.XmlWriteMode.IgnoreSchema);
Nein, du musst nur endlich anfangen zu verstehen was Du tust, und nicht irgendwas herumprobieren.
Wenn du dein DGV an eine DataTable bindest musst du überhaupt nix machen, sondern nur dataTable.WriteXml aufrufen.
Da muss nichts mehr herumgefuscht werden.
ah und wie binde ich meine dgv an meine datatable? mit der bindingsource???
edit: habd as gefunden:
http://stackoverflow.com/questions/2677446/binding-wpf-datagrid-to-datatable-using-templatecolumns
funktioniert nur leider nich, fehlermeldung hier:
dt.Rows.Add(new MyData("Row1C1", true));
dt.Rows.Add(new MyData("Row2C1", false));
"XMLSTreaming.Form1.MyData" enthält keinen Konstruktor, der 2-Argumente akzeptiert. "
Hallo Ivy,
das habe ich dir doch schon im Beitrag http://www.c-sharp-forum.de/viewtopic.php?p=657854#657854 geschrieben:
du erstellst eine DataTable (bzw. ...) und bindest dieses dann an das DGV (per DataSource).
oder ausgeschrieben
dgv.DataSource = dataTable;
ja klar hatte ich ja auch schon so, daten werden trotzdem keine gespeichert.....
DataTable t = new DataTable();
DatenTabelle.DataSource = t;
t.TableName = "TableName";
t.WriteXml("D:\\Customers.xml");
meine xml:
<?xml version="1.0" standalone="yes"?>
<DocumentElement />
Machs doch bitte richtig.
public class MyForm : Form
{
private DataTable _dtData = new DataTable("MyData");
MyForm()
{
this.InitializeComponents();
this._dtData.Columns.Add("myColumn");
this._dtData.Columns.Add("mySecondColumn");
this.dataGridView.DataSource = this._dtData;
}
private void ButtonClick(Object sender, EventArgs e)
{
this._dtData.WriteXml(Path);
}
}
Ist doch so schwer nicht? Du machst grad nix anderes als eine leere Tabelle speichern...
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
ok... tut mir ja jetzt leid das sagen zu müssen aber meine xml datei sieht mit deinem code immernoch genauso aus^^
Du musst dem DataGridView auch Daten hinzufügen! - Ansonsten hast du eben die leere Xml-Struktur. - Aber das schrieb ich bereits.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
ja klar schreib ich da daten rein 😄 es wird trotzdem nichts davon gespeichert^^
Zeig doch mal was du bisher an Code hast. - Also bei mir funktioniert der oben gepostete Code.
Beachte auch, dass das DataTable.WriteXml(string) wirklich aufgerufen werden muss (wie in meinem Beispiel durch einen Button Klick).
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
mhm ok habs jetzt hinbekommen fehler lag daran dass du die dgv wo anders initialisiert hast, ich habs jetzt in Form_Load gepackt dann ging es....
nun noch ein problem: wenn ich meine dgv beim ersten mal speicher und dann wieder lade funktioniert alles super. nur wenn ich die gespeicherte xml hineinlade in die dgv und dann neue daten hinzufügen möchte (speichern), bleibt meine xml datei wie zuvor wieder leer. wieso das?
Erstellst du beim laden eine neue DataTable? - Dann musst du die DataSource aktualisieren.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
mhm eigentlich nicht^^
XmlDocument i = new XmlDocument();
this.DatenTabelle.DataSource = this.datatable;
XmlReader xmlFile;
xmlFile = XmlReader.Create(Application.StartupPath+"\\Values.xml", new XmlReaderSettings());
dataset.ReadXml(xmlFile);
DatenTabelle.DataSource = dataset.Tables[0];
xmlFile.Close();
weil mit dgv.refresh beim speichern hab ichs schon probiert, ohne erfolg
Du machst dir das Leben irgendwie künstlich schwer.
Warum lädst du die DataTable nicht wie beim Speichern durch einfache Angabe des Xml-File Pfades?
Übrigens:
Nach dem laden folgendes:
this.datatable = dataset.Tables[0];
DatenTabelle.DataSource = this.datatable;
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
mhm ok 😄 danke geht (;
bekomm ich eigtnlich auch noch irgendwie, wie in meinem beispiel oben die datentypen von den spalten mit rein??
Hallo Leute!
Ich schreibe gerade ein Programm, in der Daten abgelegt werden sollen und abgespeichert werden sollen, damit die Informationen nicht verloren gehen. Genauer gesagt sind das Daten von Werkzeugen.
Ich habe dazu ein Datenset und ein DataTable angelegt um die Informationen in einem DGV anzeigen zu können. Soweit so gut, funktioniert alles. Dies habe ich dann noch mit 2 Filtern ausgebaut.
Wenn der Benutzer dann etwas editieren will und im Menü Strip auf Speichern klickt, soll das Programm die eingegebenen Daten speichern, im Projekt Ordner wird auch eine XML Datei erstellt, jedoch ohne Inhalt, der dazugehörige Code ist folgender:
private void speichernToolStripMenuItem_Click(object sender, EventArgs e)
{
StreamWriter stw = new StreamWriter("ProjectX.xml");
set.WriteXml(stw);
stw.Close();
StreamWriter stwbackup = new StreamWriter("ProjectX_Backup.xml");
set.WriteXml(stwbackup);
stwbackup.Close();
MessageBox.Show("Erfolgreich gespeichert und Sicherheitskopie erstellt.");
}
Wozu meinst du StreamWriter zu benötigen?
Und was ist set ( und warum heist das so )?
Ich hab als Grundlage das Buch von Galileo Computing und im Bereich Texteditor steht das auch mit StreamWriter .
set ist das DataSet, also DataSet set = new DataSet();
DataSets stellen Methoden bereit, mit denen die Daten ohne großes zutun gespeichert werden. Das gleiche gilt für das lesen von Xml-Dateien.
Wie es richtig geht steht sogar in diesem Thread.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
wie das in diesem Thread beschrieben ist, geht das denn dann auch so, dass die eingegebenen Daten nach klick auf Speichern erhalten bleiben, bzw sind die dann gespeichert? Weil das ist das was ich noch hinbekommen muss, oder gibt es da sogar noch eine bessere und leichtere Alternative? 😃
Wieso sollten die Daten verschwinden wenn du Speichern klickst?
// Edit: Schau dir mal meine Beiträge oben an.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Weil das Erstellen einer XML Datei mir bereits gelungen ist.
Wenn ich das Programm jedoch schließe sind die Daten, die in der DataGridView eingegeben worden sind weg.
Und das sollte ja vermieden werden. 😃
Dann musst du die Xml-Datei bei Start eben wieder laden?!
Analog zum oben genannten DataSet.WriteXml(string) gibt es auch die Methode DataSet.ReadXml(string), mit der das Xml wieder in das DataSet gefüllt wird.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Sorry,
aber so ein Programm schreibe ich zum ersten Mal, vorher habe ich das immer per Access DB gemacht, und per Assistenten in VS eingebunden, dadurch wurde das direkt übernommen.
Also habe ich einfach nur einen Befehl vergessen?!
oder muss ich dann wenn meine MainForm geladen wird einfach die XML da reinladen? So richtig bin ich dir da leider noch nicht hintergestiegen.
Natürlich musst du es bei Start der Anwendung laden. - Ansonsten stehen dir die Daten dort ja nicht zur Verfügung.
Als Beispiel, stellen wir uns vor du hast ein Model, was dir die Sachen lädt und speichert:
public class MyModel
{
private DataSet _myData;
public DataSet MyData
{
get { return _myData; }
}
public DataTable this[string sTableName]
{
get { return _myData.Tables[sTableName]; }
}
// Methode um die Xml-Datei in das DataSet einzulesen
public bool LoadData(string xmlFile)
{
bool bSuccess = false;
try
{
// Xml-Datei laden
this._myData = new DataSet();
this._myData.ReadXml(xmlFile);
if(this._myData.Tables.Count > 0)
bSuccess = true;
}
catch
{
bSuccess = false;
}
return bSuccess;
}
// Methode zum speichern der Daten in ein Xml-File
public bool SaveData(string xmlFile)
{
bool bSuccess = false;
try
{
// Xml-Datei laden
this._myData = new DataSet();
this._myData.WriteXml(xmlFile);
bSuccess = true;
}
catch
{
bSuccess = false;
}
return bSuccess;
}
}
In deinem Formular kannst du nun eine Instanz deines Models halten, und die Daten laden und speichern.
Dabei reichen dir Grundlegend die folgenden Zeilen Code:
public partial class MyForm : Form
{
private MyModel _model = new MyModel();
protected override OnLoad()
{
// Daten laden
if(this._model.LoadData("myXmlFile.xml"))
{
this.dataGridView.DataSource = this._model["MeineTabelle"];
}
}
private void MyButton_Click(Object sender, EventArgs e)
{
if(this._model.SaveData("myXmlFile.xml"))
MessageBox.Show("Erfolgreich gespeichert und Sicherheitskopie erstellt.");
}
}
Grundlegend sollten dir die Informationen nun aber reichen. - Ist jetzt nicht alles optimal und es fehlt zum Beispiel dein Backup aber ansonsten zeigt es wie du es anstellen kannst.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Erst einmal Vielen Dank für die Antwort, ich werde es gleich direkt ausprobieren. 😃
Jetz nochmal eine andere Frage. In meinem Programm habe ich es mit StreamWriter gemacht. Und ein Freund von mir hat so ein ähnliches Programm auch geschrieben, ebenfalls mit abspeichern in XML. Ich hab ihn dann gefragt wie er es gemacht hat.
Er hat das dann so angestellt:
Wenn der Benutzer im Menü_Strip, auf die Schaltfläche speichern klickt, wird gespeichert, quasi dasselbe, wie mit einem Button. Dazu nannte er mir folgenden Quellcode, der exakt derselbe is, den ich auch verwendet habe. Also ist es möglich das auch mit StreamWriter zu machen? Oder hat das eventuell soga Buggs, die ich erst fixen muss?
StreamWriter stw = new StreamWriter("DateiName.xml");
DATASETVARIABLENNAME.WriteXml(stw);
stw.Close();
Ich habe gerade eben den obigen Quellcode mit StreamWriter verwendet. In meiner ersten Form hat das Programm funktioniert, und die Informationen gespeichert. Als ich dasselbe dann in meine 2. Form anwenden wollte gab es die Fehlermeldung bei folgender Zeile :
dataGridView1.DataSource = set.DefaultViewManager;
Daneben stand: Die untergeordnete Liste für das Feld Werkzeuglager kann nicht erstellt werden.
Was kann ich tun?
Wie lautet denn die konkrete Exception?
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Also beim Öffnen der 2. Form, in der die Daten in der DGV editiert werden und wo gespeichert werden soll steht folgender code:
public partial class Stufenbohrer : Form
{
DataSet set = new DataSet();
DataTable table;
public Stufenbohrer()
{
InitializeComponent();
NeueTabelle();
XmlDataDocument xmldd = new XmlDataDocument();
xmldd.DataSet.ReadXml("DutecDB.xml");
set = xmldd.DataSet;
dataGridView1.DataSource = set.DefaultViewManager;
Und als Quellcode der Schaltfläche Speichern steht das hier:
private void speichernToolStripMenuItem_Click(object sender, EventArgs e)
{
StreamWriter stw = new StreamWriter("DutecDB.xml");
set.WriteXml(stw);
stw.Close();
string strmeldung = "Erfolgreich gespeichert und Sicherheitskopie erstellt.";
DialogResult result = MessageBox.Show(strmeldung,
Application.ProductName,
MessageBoxButtons.OK,
MessageBoxIcon.Information,
MessageBoxDefaultButton.Button1);
}
Und wie war meine Frage?
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Ich kann dir leider nicht ganz folgen, benötigst du weitere Details zum Fehler?
Habe ich bereits;)
deshalb bin ich ja davon ausgegangen, dass eventuell ein paar Details von meiner Fehlermeldung fehlen.
Oder meinst du die Try and Catch abfrage?
Es ist völlig richtig, das Details der Fehlermeldung fehlen, daher habe ich ja noch einmal explizit dannach gefragt.
Interessant wäre eben die volle Exception.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Fehlermeldung:
Die untergeordnete Liste für das Feld Werkzeuglager kann nicht erstellt werden.
So lautet die komplette Fehlermeldung.
Wenn du damit auch nicht so wirklich etwas anfangen kannst, kann ich dir mein komplettes Projekt auch per Email zu kommen lassen.
In meinem Galileobuch ist ein Beispiel wie man einen Texteditor realisiert. Ist das in meinem Fall denn auch möglich meine Daten als .txt File zu speichern an Stelle eines .xml Files?
Ich denke ich weiß jetzt wo der Fehler liegt. Ich habe gerade noch einmal ausprobiert ob eine XML Datei erstellt wird, wenn ich auf Speichern drücken. Demnach trifft dies wirklich zu.
Wenn ich dann folgenden Code beim Laden der Form hinschreibe:
XmlDataDocument xmldd = new XmlDataDocument();
xmldd.DataSet.ReadXml("DateiName.xml");
set = xmldd.DataSet;
dataGridView1.DataSource = set.DefaultViewManager;
werden die Daten geladen die ich in VS eingegeben habe. Schließe ich das Programm wieder und versuche es erneut zu öffnen sind die Daten verloren.
Vielleicht gibt es ja einen Befehl der sagt, wenn "DateiName.xml" schon vorhanden mit Daten, ersetze diesen und öffne die neue Datei.
Ich vermute mal du startest die Anwendung im Debugmodus und die XML-Datei liegt als Datei im Projekt vor, die immer in den Ausgabeordner geschrieben wird?!
In dem Fall wird deine Datei immer wieder überschrieben.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Das bedeutet jetzt für mich?
Ist der Quellcode mit StreamWriter also doch richtig?
Beziehungsweise was muss ich nun tun?
Und in meiner Form ist kein try und kein catch Befehl vorhanden stehts If-Anweisungen.
Nur wenn meine Vermutung richtig ist. 😃
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Ohne Visual Studio ist genau derselbe Fehler vorhanden 😦
Grundlegend kann ich mir das nicht vorstellen, dann machst du etwas verkehrt was du noch nicht offenbart hast.
Ich häng dir mal ein Testprojekt an.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |
Vielen Dank für dein Beispiel Programm.
Ich versuche mal denselben QuellCode zu nehmen und den in meiner Version anzupassen, wenn ich da dann trotzdem nicht weiter kommen sollte, werde ich mein Projekt in meiner Dropbox hochladen und den Link hier preisgeben.
Bei mir funktioniert es immernoch nicht.
Hier der Link von meiner Dropbox, in dem Programm hab ich den Quellcode exakt übernommen, die Klasse hinzugefügt usw.
Hi Paddy93,
komplette Projekte hier zu posten ist eigentlich nicht erwünscht. Siehe dazu [Hinweis] Wie poste ich richtig?, Punkt 4.1.
Ich finde es ehrlich gesagt auch nicht zuviel verlangt, die auftretende Exception hier mitsamt CallStack usw. zu posten. Es ist doch nur Copy & Paste...
Christian
Weeks of programming can save you hours of planning
Ist ja im großen und ganzen auch kein komplettes Programm.
In dem TestProgramm funktioniert das Speichern gar keine Frage.
Der Unterschied zwischen dem Test Programm und meinem ist, so denke ich, das die Spalten der DataGridView, manuell über den XML Code hinzugefügt wurden.
In meinem Programm habe ich diese über
table.Columns.Add("Name",typeof(string));
programmiert.
Ich denke einfach da fehlt nur noch eine winzige Kleinigkeit und ich komm da einfach nicht drauf. 😦
Und wie du das mit der Exception meinst verstehe ich leider nicht, sonst hätte ich das ja schon längst gemacht um euch einen besseren Eindruck zu verschaffen wo genau mein Problem liegt.
Paddy
Habe das Speichern soweit garnicht schlecht hinbekommen.
Jetzt bekomme ich jedoch eine Fehlermeldung, die ich vorher schon einmal gepostet hatte.
Fehlermeldung:
Argument Exception wurde nicht behandelt. Die untergeordnete Liste konnte nicht hinzugefügt werden.
Beim Debuggen erscheint wohl noch mein Startformular. Wähle ich dann in meinem Menüstrip eine Kategorie aus, haperts bei folgendem Befehl:
dataGridView1.DataSource = set.DefaultViewManager;
Muss ich in VisualStudio irgendwas bestimmtes einstellen?