Autor |
Beitrag |
error404
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Mi 12.01.11 19:52
Hallo ich bin neu hier und hoffe ihr könnt mir helfen.
Ich habe hier eine kleine Consolen-Anwendung geschrieben, die automatisch Daten in eine Xml-Datei schreibt.
Dieses würde ich jetzt gerne erweitern, sodass ich über die Console neue Einträge schreiben, vorhande Einträge in der XML-Datei suchen und die vorhanden Beiträge dann auch ändern kann.
Nur habe ich leider keine Idee wie ich das machen kann.
Meine Frage ist also, wie ich mein Vorhaben am besten in die Tat umsetzen kann.
Mein Programm sieht derzeit so aus.
Die Klassendatei
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
| using System; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.IO;
namespace SchulV6 { [XmlRoot("Schuelerliste")] public class SchuelerListe { [XmlElement("Listenbezeichner")] public string Listenname;
[XmlArray("SchuelerArray")] [XmlArrayItem("Schueler")] public Schueler[] Schueler;
public SchuelerListe() { }
public SchuelerListe(string name) { this.Listenname = name; } }
public class Schueler { [XmlElement("vorname")] public string vorname;
[XmlElement("nachname")] public string nachname;
[XmlElement("note")] public string note;
[XmlElement("gebDatum")] public string gebDatum;
[XmlElement("Wohnort")] public string ort;
public Schueler() { }
public Schueler(string vorname, string nachname, string note, string gebDatum, string ort) { this.vorname = vorname; this.nachname = nachname; this.note = note; this.gebDatum = gebDatum; this.ort = ort; }
public void Ausgabe() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\nVorname:{0}\nNachname:{1}\nNote:{2}\n\ngebDatum:{3}\n\nAdresse:{4}\n", vorname, nachname, note, gebDatum, ort); Console.ResetColor(); } } } |
Das Programm
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| using System; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.IO;
namespace SchulV6 { class Program { static void Main(string[] args) { SchuelerListe catalog = new SchuelerListe("TA 92"); catalog.Listenname = "TA 92"; Schueler[] schueler = new Schueler[2];
schueler[0] = new Schueler("Max", "Planck", "2", "1945", "Berlin"); schueler[1] = new Schueler(); schueler[1].vorname = "Albert"; schueler[1].nachname = "Einstein"; schueler[1].note = "1"; schueler[1].gebDatum = "1930"; schueler[1].ort = "Hamburg"; catalog.Schueler = schueler;
XmlSerializer serializer = new XmlSerializer(typeof(SchuelerListe)); FileStream fs = new FileStream("Schuelerliste.xml", FileMode.Create); serializer.Serialize(fs, catalog); fs.Close(); catalog = null;
fs = new FileStream("Schuelerliste.xml", FileMode.Open); catalog = (SchuelerListe)serializer.Deserialize(fs); serializer.Serialize(Console.Out, catalog); Console.ReadLine(); } } } |
Ich bin für jede Hilfe dankbar
Gruß,
Marcel
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mi 12.01.11 20:45
Hallo Marcel,
erst wollte ich dich auf meinen gerade geschriebenen Beitrag zu www.c-sharp-forum.de....php?p=629297#629297 hinweisen, aber dann habe ich gesehen, daß du das ja schon richtig implementiert hast - Kompliment!
Ich würde an deiner Stelle zuerst einmal in der Main-Methode ein Menü implementieren, mit dem du dann dem Anwender die Auswahl der einzelnen Funktionalitäten anbietest ("Neuer Schüler", "Schüler löschen", "Schüler suchen", "Liste sortieren" etc.)
Und dann implementierst du in deiner Klasse "SchuelerListe" die einzelnen Methoden dafür.
(nur statt dem "Schueler[]" solltest du besser die dynamische "List<Schueler>" benutzen, um dann einfach mittels Add(...) einen neuen Schüler anzulegen, mittels "Remove(...)" zu entfernen etc.).
Schau am besten in die MSDN, um die einzelnen Methoden der List<>-Klasse besser kennenzulernen.
Auch dir wünsche ich viel Erfolg!
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Mi 12.01.11 22:05
Danke für deine Antwort.
Verstehe ich es richtig, dass ich die List<Schueler> in den unteren Code kommt oder muss ich diese in den oberen implementieren? Die Frage stelle ich deshalb, da ich ich mit zwei Dateien arbeite.
Wenn ich mir dein Beispiel aus dem Nachbar-Thread ansehe, verstehe ich es nämlich so, dass die List in den unteren kommt.
Dem Anwender möchte ich beim Start der Consolen-Anwendung erstmal nur diese Möglichkeiten bieten:
"Neuer Schüler"(Taste N), "Schüler suchen"(Taste S) und Programm beenden.
Wenn der Anwender sich für die Suche entscheiden sollte und der gesuchte Schüler ausgegeben wird bekommt er dann auch die Möglichkeit des Löschens.
Noch eine ganz andere Frage...
Ist es möglich den Schülern eine ID zu zuweisen die dann automatisch fortgeführt wird?? Ich meine das so... Schüler 1 bekommt die ID 100, wenn ich dann aber einen neuen Schüler eintrage würde ich es gerne so haben, dass Schüler 2 automatisch die ID 102 bekommt.
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 13.01.11 19:19
Hallo und schönen Abend,
stimmt, ich hatte vorher nicht gesehen, daß du ja in der Main()-Methode noch ein Schueler[] anlegst, du solltest selbstverständlich das in der SchuelerListe-Klasse erstellen und benutzen.
Also in etwa so (extra schon mit List<>  ):
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| public class SchuelerListe { public string Listenname;
public List<Schueler> Schueler = new List<Schueler>();
public SchuelerListe() { }
public SchuelerListe(string name) { this.Listenname = name; } } |
Und die Benutzung in der Main dann in etwa so:
C#-Quelltext 1: 2: 3: 4:
| SchuelerListe catalog = new SchuelerListe("TA 92");
Schueler schueler = new Schueler("Max", "Planck", "2", "1945", "Berlin"); catalog.Schueler.Add(schueler); |
Ein bißchen unelegant ist die Namensbenennung, da "Schueler" sowohl Einzahl als auch Mehrzahl bedeuten kann...
P.S. Statt öffentlichen Feldern solltest du besser Eigenschaften benutzen, d.h.
C#-Quelltext 1:
| public string Listenname [ get; set; } |
Dies erleichtert auch die Serialisierung, da diese standardmäßig alle Eigenschaften einer Klasse benutzt (nicht die internen Felder).
-----
Und für die Id könntest du eine "static int LastId" verwenden, welche du dann in der Schueler-Klasse anlegst und im Konstruktor erhöhst.
Jedoch entspricht ja eigentlich der Index in der Schueler-Liste deiner Id (nur bei Anlegen einer Datenbank-Tabelle wäre eine fortlaufende Id sinnvoll, um sog. Fremdschlüssel (Foreign Keys) zu verwalten).
Für diesen Beitrag haben gedankt: error404
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Fr 14.01.11 13:37
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 14.01.11 14:24
Hallo,
sorry, meinte natürlich:
C#-Quelltext 1:
| public string Listenname { get; set; } |
ab C#3.0, d.h. VS 2008 kann man so automatische Eigenschaften erzeugen, d.h. der Compiler erzeugt dann intern daraus:
C#-Quelltext 1: 2: 3: 4: 5: 6:
| public string Listenname { get { return listenname; } set { listenname = value; } } private string listenname; |
(also so, wie du es geschrieben hast  )
Die Felder sollten aber auf jeden Fall 'private' sein.
Hast du denn sonst noch eine Frage dazu?
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Fr 14.01.11 14:32
Hallo,
Fragen dazu habe ich erstmal keine.
Ich werde das dann gleich mal Anwenden. Falls Probleme auftreten sollten die ich nicht selber lösen kann, melde ich mich dann wieder hier. Natürlich auch wenn ich doch noch Fragen haben sollte.
Danke für deine Hilfe und Tipps
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Fr 14.01.11 15:44
Ich habe die Klasse gerade meinen Klassen-Code in die Eigenschaften geändert bekomme jetzt aber zwei Fehlermeldungen.
Ersteinmal der Code
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| public SchuelerListe() { }
public SchuelerListe(string name) { this.Listenname = name; } }
public class Schueler { [XmlElement("vorname")] public string vorname;
[XmlElement("nachname")] public string nachname;
[XmlElement("note")] public string note;
[XmlElement("gebDatum")] public string gebDatum;
[XmlElement("Wohnort")] public string ort;
public Schueler() { }
public string Listenname { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public string Note { get; set; }
public string gebDatum { get; set; }
public string Ort { get; set; } |
Jetzt heißt es aber, dass eine Mehrdeutigkeit durch "gebDatum" besteht und die Klasse Schueler keinen Konstruktor enthalt, der 5 Argument zulässt.
Woran kann das liegen?
------------
Zum Thema Private:
Ich habe irgendwo gelesen, dass es es nicht gehen soll, wenn ich etwas in Private schreibe und ich in einer XML-Datei speichern möchte. Oder gilt das nur für die Klassen?
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 14.01.11 16:04
Du sollst ja auch die Eigenschaften anstatt der öffentlichen Felder benutzen, d.h. entferne letztere (und die XML-Attribute brauchst du nur bei Bedarf hinzufügen, d.h. wenn du also explizit andere Namen verwenden willst).
Und den Konstruktor für Schueler mit den fünf Parametern scheinst du ja selber gelöscht zu haben...
P.S: Und Eigenschaften sollten immer mit einem Großbuchstaben anfangen, d.h. "GebDatum"
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Fr 14.01.11 17:26
Da hatte ich wohl etwas falsch verstanden und es direkt korrigiert.
Jetzt habe ich aber ein anderes, aber auch nur kleines Problem. Die XML-Datei wird zwar erstellt aber die Daten die gespeichert werden sollen, sind nicht auffindbar.
Ich glaube du erkennst sofort wo der Fehler liegt
Hier Code
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| static void Main(string[] args) { SchuelerListe catalog = new SchuelerListe("TA 92"); catalog.Listenname = "TA 92";
Schueler TAler1 = new Schueler("Max", "Planck", "2", "1945", "Berlin"); catalog.Schueler.Add(TAler1); Schueler TAler2 = new Schueler("Marcel", "Steinke", "1", "1986", "Gütersloh"); catalog.Schueler.Add(TAler2);
XmlSerializer serializer = new XmlSerializer(typeof(SchuelerListe)); FileStream fs = new FileStream("Schuelerliste.xml", FileMode.Create); serializer.Serialize(fs, catalog); fs.Close(); catalog = null;
fs = new FileStream("Schuelerliste.xml", FileMode.Open); catalog = (SchuelerListe)serializer.Deserialize(fs); serializer.Serialize(Console.Out, catalog); Console.ReadLine(); } |
Habe ich vielleicht irgendwo ein "catalog" vergessen?
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 14.01.11 18:34
Hallo Nachbar
(habe jetzt erst gesehen, daß du ja aus GT kommst -)
was genau meinst du? Wird die XML-Datei erstellt, aber enthält keine Schueler-Daten?
Wie sieht denn jetzt deine SchuelerListe-Klasse aus?
P.S. Das "catalog.Listenname = "TA 92";" brauchst du nicht nochmal explizit ausführen, da du ja den Listennamen schon im Konstruktor übergeben hast.
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Fr 14.01.11 18:43
Richtig, die XML-Datei wird erstellt aber enthält keine Schueler-Daten.
-----
Hier meine jetzige Klasse Schuelerliste
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57:
| [XmlRoot("Klassenliste")] public class SchuelerListe { [XmlElement("Klasse")] public string Listenname;
[XmlArray("Mitglieder")] [XmlArrayItem("TAler")] public List<Schueler> Schueler = new List<Schueler>();
public SchuelerListe() { }
public SchuelerListe(string name) { this.Listenname = name; } }
public class Schueler { public string Vorname { get; set; } private string vorname;
public string Nachname { get; set; } private string nachname;
public string Note { get; set; } private string note;
public string GebDatum { get; set; } private string gebDatum;
public string Ort { get; set; } private string ort;
public Schueler() { }
public Schueler(string vorname, string nachname, string note, string gebDatum, string ort) { this.vorname = vorname; this.nachname = nachname; this.note = note; this.gebDatum = gebDatum; this.ort = ort; }
public void Ausgabe() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\nVorname:{0}\nNachname:{1}\nNote:{2}\n\ngebDatum:{3}\n\nOrt:{4}\n", vorname, nachname, note, gebDatum, ort); Console.ResetColor(); } } |
-----------------------------------------------------------------------------------------------------------------------------------------
EDIT:
Ich habe hier noch einen Teil von einem vorherigen Programm bzw. einer Vorversion von dem das ich jetzt schreibe.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125:
| while (ende == false) { Console.WriteLine("h - Person hinzufügen"); Console.WriteLine("s - Person suchen"); Console.WriteLine("e - Programm beenden"); Console.Write("Befehl:"); ConsoleKeyInfo Befehl; Befehl = Console.ReadKey(true); switch (Befehl.Key) { case ConsoleKey.S: AuswahlPer(ref Sch, ref PersonList,ref path); break; case ConsoleKey.H: AddPer(ref PersonList,ref path); break; case ConsoleKey.E: ende = true; break; } }
Console.ReadKey();
}
public static void AddPer(ref List<string> PersonList,ref string path) { StreamWriter WPersonTXT = File.AppendText(path); Console.Write("\n\nVorname:"); string vorname = Console.ReadLine(); PersonList.Add(vorname); WPersonTXT.WriteLine(vorname); Console.Write("Nachname:"); string nachname = Console.ReadLine(); PersonList.Add(nachname); WPersonTXT.WriteLine(nachname);
Console.Write("Note:"); string note = CheckNote(); PersonList.Add(note); WPersonTXT.WriteLine(note);
Console.Write("gebDatum{Tag.Monat.Jahr}(1985-1990):"); string datum = CheckDatum(); PersonList.Add(datum); WPersonTXT.WriteLine(datum);
Console.Write("Adresse(Ort):"); string adresse = Console.ReadLine(); PersonList.Add(adresse); WPersonTXT.WriteLine(adresse);
WPersonTXT.Close(); Console.WriteLine(); }
public static string CheckNote() { int Note = 9; while (Note < 1 || Note > 6) Note = Convert.ToInt16(Console.ReadLine()); return Convert.ToString(Note); }
public static string CheckDatum() { DateTime datum = DateTime.Today; string Eingabe = "Test"; bool ok = false;
while (ok == false) { if (DateTime.TryParse(Eingabe, out datum) == true) datum = Convert.ToDateTime(Eingabe); if (datum.Year > 1984 && datum.Year < 1996 == true) ok = true; else Eingabe = Console.ReadLine(); } return Convert.ToString(String.Format("{0:dd.MM.yyyy}", datum)); }
public static void AuswahlPer(ref Schueler Sch, ref List<string> PersonList,ref string path) { string gesVorname = "test"; string gesNachname = "test"; int gesID = 0; Console.Write("\n\nges.Vorname:"); gesVorname = Console.ReadLine();
Console.Write("ges.Nachname:"); gesNachname = Console.ReadLine();
for (int ie = 0; ie <= PersonList.Count - 1; ie += 5) { if (PersonList[ie].Contains(gesVorname) && PersonList[ie + 1].Contains(gesNachname)) gesID = ie; }
Sch.MetVorname = PersonList[gesID]; Sch.MetNachname = PersonList[gesID + 1]; Sch.MetNote = PersonList[gesID + 2]; Sch.MetgebDatum = PersonList[gesID + 3]; Sch.MetAdresse = PersonList[gesID + 4];
Sch.Ausgabe();
Console.WriteLine("Note ändern?(ja/nein):"); string befehl = Console.ReadLine(); if (befehl.Contains("ja")) { Console.Write("Note:"); PersonList[gesID + 2] = CheckNote(); StreamWriter WPersonTXT = new StreamWriter(path); for (int je = 0; je < PersonList.Count; je++) WPersonTXT.WriteLine(PersonList[je]); WPersonTXT.Close();
} Console.WriteLine(); }
} } |
Kann ich diesen Teil für mein Programm verwenden wenn ich es für XML-Anpasse?
Dieser Code wurde wie man sieht für den StreamWriter geschrieben, ist aber so in etwa das was ich mit meinem Programm machen möchte(wenn ich es erweiter ist es sogar das sogar genau).
|
|
Th69
      

Beiträge: 4795
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Sa 15.01.11 04:09
Sorry @error404,
aber ich glaube, so wird das nichts.
Dein Programm wird anscheinend immer konfuser, da du meine geposteten Sachen nicht richtig zu verstehen scheinst.
Am besten, du schaust dir mal mein Beispielprojekt 'PersonManagement' an, das ich bei dem Artikel www.bitel.net/dghm11...ion_von_2_Forms.html unten verlinkt habe.
Die beiden interessanten Klassen sind im Unterordner 'Logic' zu finden: Person und Hobby.
Auch diese serialisiere ich einfach in eine XML-Datei (in der MainForm beim menuItemOpen bzw. menuItemSave).
Hier noch mal in Kürze die wichtigen Punkte:
1. Eigenschaften anstatt öffentliche Felder verwenden
2. wenn du die "automatischen Eigenschaften" verwendest { get; set; }, dann brauchst du selber keine privaten Felder mehr dafür anzulegen (das macht dann der Compiler intern)
3. du mußt dann aber auch die Eigenschaften intern verwenden, z.B. im Konstruktor "Vorname = vorname;"
Außerdem habe ich noch mal in mein Projekt geschaut:
es reicht wenn du einfach die Klassen als serialisierbar kennzeichnest:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| [Serializable] class SchuelerListe {
}
[Serializable] class Schueler {
} |
Und deine anderen Methoden solltest du dann noch mal neu implementieren...
|
|
error404 
Hält's aus hier
Beiträge: 8
XP, Win7
C#(VS 2010)
|
Verfasst: Sa 15.01.11 13:46
Ich habe die privaten Felder jetzt auch der Klasse enternt und siehe da, die Beispieldaten werden in der XML-Datei gespeichert.
-------------
Danke für das super Beispiel.
Nur dazu habe ich noch eine Frage.
Kann ich es so ähnlich schreiben wie ich es in meinem vorherigen Beitrag gepostet(der untere C#-Quellcode) habe??? In deinem Programm kann ich das leider nicht so gut erkennen, da du es mit einer Windows-Form geschrieben hast und ich noch nie mit solchen gearbeitet habe.
|
|
|