| Autor |
Beitrag |
coolace
      
Beiträge: 141
|
Verfasst: So 17.08.08 16:29
Hy,
ich versuch mir eine sauber Programmierung anzugewöhnen um mögliche Fehler zu vermeiden
und besser zu werden. Ich habe folgendes Problem, ich less über eine Textbox einen Namen
ein und über einen Datetimepicker das Datum ein. Hab mir dafür eine Klasse daten erzeugt mit
den Property, die klasse speichert 2 strings gebname und gebdatum und hat eine Methode tostring()
wo beide Daten mit Leerstring zusasmmenfasst. Z.B. Hans 27.01.1980
Durch ein Button wird ein Eintrag erzeugt, und hier kommt die InvalidOperationExcextion.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| public void Eintragadd(string sd, DateTime date) { daten d = new daten(); d.Gebname = sd; d.Gebdatum = date.ToShortDateString(); liste.Add(d); foreach (daten temp in liste) { liste.Add(temp.ToString()); } } |
Was ist hier falsch ?
LG
Coolace
Moderiert von Christian S.: C#-Tags hinzugefügt
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 17.08.08 16:53
Hallo!
Du benutzt in der Schleife sowohl liste als die Liste, durch die Du iterierst als auch als Liste, in die Du Elemente einfügst. Das klappt nicht.
Noch ein paar Hinweise, die nicht mit dem unmittelbaren Problem zusammen hängen:
- Typen immer groß schreiben. Also daten -> Daten
- ArrayList ist veraltet, also lieber mit List<Daten> arbeiten. Dadurch entällt auch etwaiges rumgecaste. Andere Möglichkeit: BindingList<Daten> (siehe unten)
- Wenn Du ein Datum speichern willst, dann speichere es als DateTime und nicht als String
- Abkürzungen wie "Gebname" sparen in moderenen IDEs mit Codevervollständigung fast keinerlei Tipparbeit, vermindern aber die Lesbarkeit sehr.
Nun noch zur BindingList<Daten>. Zu benutzen praktisch so wie eine ArrayList. Vorteil: Sie stellt Ereignisse bereit, damit Komponenten wie die Listbox mitbekommen, wenn Einträge hinzugefügt oder entfernt werden. Dann aktualisieren die sich von selber.
Benutzung wäre so:
- privates Feld: BindingList<Daten> datenListe;
- im Load-Ereignis (oder Konstruktor) der Form dann das hier: C#-Quelltext 1: 2:
| datenListe = new BindingList<Daten>(); dieListbox.DataSource = datenListe; |
Wenn Du nun der datenListe ein Item hinzufügst, dann bekommt die Listbox das automatisch mit. Das ist viel eleganter, als sich selber um die Anzeige kümmern zu müssen.
Grüße
Christian
P.S.: Es gibt auch noch die Möglichkeit, dass die Listbox mitbekommt, wenn Du ein Geburtsdatum oder einen Namen änderst, nachdem das Item schon eingefügt wurde. Aber dazu späer mehr 
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mo 18.08.08 11:48
vielen Dank für deine Hilfe, hab das Problem gesehen dank deinem Hinweis.
Meine Listbox heißt lbox und bin dann beim tippen mit lbox und liste durcheinander
gekommen so das es aussieht als würde er im Kreis kopieren.
in die Databinding geschichten werd ich mich demnächst mal einarbeiten.
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mo 18.08.08 21:53
ich habe das getestet und einen merkwürdigen Fehler festgestellt, sobald ich eine leere Datei habe und das Programm starte kann ich beliebig viele Personen mit geburtsdatum einfügen. Sobald ich aber die Datei schließe, die Einträge speicher und wieder öffne und zu diesen Einträgen einen Hinzufüge beokmm ich eine InvalidCastException gleich bei der foreachschleife foreach (daten temp in liste) <--hier
Ich hab auch auf eure Empfehlung hin den String auf Datetime umgestellt in der Klasse.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| public void Eintragadd(string sd, DateTime date) { daten d = new daten(); d.Gebname = sd; d.Gebdatum = date; liste.Add(d); liste.TrimtoSize(); lbox.items.clear(); foreach (daten temp in liste) { lbox.Add(temp.ToString()); } } |
Er sagt was von Das Objekt des Typ System.string kann nicht in Typ WindowsApplicaton11.daten umgewandelt werden
LG
Coolace
Moderiert von Christian S.: C#-Tags hinzugefügt
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 18.08.08 22:15
Öhm, lies doch mal bitte Deinen Beitrag durch und überlege, ob Dir jemand helfen kann, der Dein Programm nicht kennt.
Wie speicherst Du die Daten?
Wie lädst Du die Daten?
Ich kann Dir auch nicht mehr sagen, als die Exception schon sagt: Da ist ein String in der Liste und Du versuchst, in als Daten zu verwenden. Alles weitere ist ein Fall für die Astrologie
//edit: Und jetzt benutze doch endlich List<Daten>! Dann kann sowas gar nicht passieren! ArrayList ist ALT und TOT für neue Projekte!
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mo 18.08.08 22:22
Sorry,
hier mein komplettes Programm
Hauptprogramm
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:
| public partial class Form1 : Form { string n,datum; Int32 startindex; ArrayList liste = new ArrayList(); public Form1() { InitializeComponent(); try
{ Dateierstellung(); lbldate.Text = DateTime.Now.ToLongDateString(); liste.AddRange(File.ReadAllLines(@"E:\Butler\geburtstag.txt")); Geburtstagskind(); } catch (Exception) { MessageBox.Show(this, "Eine der Dateien existiert nicht", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
private void btnexit_Click(object sender, EventArgs e) {
Int32 i = 0; string[] speicher = new string[liste.Capacity]; foreach (daten temp in liste) { speicher[i] = temp.ToString(); i++; } File.WriteAllLines(@"E:\Butler\geburtstag.txt",speicher); this.Close(); }
private void btnadd_Click(object sender, EventArgs e) { geburtstag geb = new geburtstag(); geb.Show(this); } private void Dateierstellung() {
if (File.Exists(@"E:\Butler\geburtstag.txt")) { } else { File.Create(@"E:\Butler\geburtstag.txt"); }
}
private void Form1_Load(object sender, EventArgs e) { }
public void Eintragadd(string sd, DateTime date) { daten d = new daten(); d.Gebname = sd; d.Gebdatum = date; liste.Add(d); liste.TrimToSize(); lbox.Items.Clear(); foreach (daten temp in liste) { lbox.Items.Add(temp.ToString()); } }
public void Geburtstagskind() { foreach (string temps in liste) { lbox.Items.Add(temps); }
}
private void btndel_Click(object sender, EventArgs e) { try { lbox.Items.RemoveAt(lbox.SelectedIndex); } catch (IndexOutOfRangeException) {
MessageBox.Show(this, "Sie müssen einen Eintrag auswählen", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); } } |
Klasse
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: 25: 26:
| class daten { string gebname; DateTime gebdatum;
public string Gebname { get { return gebname; } set { gebname = value; } }
public DateTime Gebdatum { get { return gebdatum; } set { gebdatum = value; } }
public override string ToString() { string s = gebdatum.ToShortDateString() + " " + gebname; return s; } } } |
Moderiert von Christian S.: C#-Tags hinzugefügt
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 18.08.08 22:31
Jo. Du liest die Liste hiermit ein:
C#-Quelltext 1:
| liste.AddRange(File.ReadAllLines(@"E:\Butler\geburtstag.txt")); |
Das sind alles Strings. Und die versuchst Du als Daten zu verwenden. Kann nicht klappen.
Du musst die Daten so speichern, dass Du sie hinterher wieder in ein Daten-Objekt einlesen kannst. Du brauchst also im Prinzip eine Umkehrung der ToString-Methode, die Du auf jeden Zeile der Datei anwendest, damit daraus wieder Daten-Objekt wird.
Viel besser wäre es wohl, das Speichern und Laden dem XmlSerializer zu überlassen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| List<Daten> liste = new List<Daten>();
liste.Add(...); liste.Add(...);
XmlSerializer xs = new XmlSerializer(typeOf(List<Daten>));
using(FileStream fs = File.Create(@"E:\Butler\geburtstag.xml")) xs.Serialize(liste, fs); using(FileStream fs = File.OpenRead(@"E:\Butler\geburtstag.xml")) liste = (List<Daten>) xs.Deserialize(fs); |
Und nun noch eine Bitte: Du hast sicherlich bemerkt, dass unter jedem Deiner Postings ein Hinweis steht, dass ich C#-Tags hinzugefügt habe. Mache das bitte demnächst selber. Hier die Erklärung dazu.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Di 19.08.08 08:23
Hy,
erstmal vielen vielen Dank für deine Mühe mir weiterzuhelfen und entschuldige wegen den C# Tags, hab ich bei den Boardregelen überlesen und daher nicht gemacht. Werd mich bessern aber danke für den Hinweis, macht den code gleich übersichtlicher.
Jetzt kapier ich auch warum der Compiler so ein Problem damit hat. XML wär eine feine Sache, muss ich dann über meine Klasse noch wie beim Binärformat [Serialisable] davor machen oder reicht das was du hingeschrieben hast ?
Gruß
Coolace
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 19.08.08 10:36
Wenn Du die Serialisierung nicht irgendwie beeinflussen willst (also den Knoten andere Namen geben als die Properties haben oder eine Property als Attribut anstatt als Knoten serialisieren), dann sollte der Serializer eigentlich mit den allermeisten Klassen klar kommen, ohne dass man mehr machen muss; als ich geschrieben habe. Es werden halt alle Properties serialisiert, die einen Getter oder Setter haben.
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Di 19.08.08 21:29
sorry aber ich hab das so hinzugefügt wie du es beschrieben hast und als es an das Speichern ging
sagt er InvalidOperationException (beim Generieren des XML Dokuments ist ein Fehler aufgetreten.
Hab ich irgendwas übersehen oder muss ich irgendwas an meinem Quellcode ändern
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: 25: 26:
| private void btnexit_Click(object sender, EventArgs e) {
using(FileStream fs = File.Create(@"E:\Butler\geburtstag.xml")) xs.Serialize(ArrayList, fs); this.Close(); }
und
InitializeComponent(); try
{ Dateierstellung(); lbldate.Text = DateTime.Now.ToLongDateString(); using(FileStream fs = File.OpenRead(@"E:\Butler\geburtstag.xml")) liste = (ArrayList) xs.Deserialize(fs); Geburtstagskind(); } catch (Exception) { MessageBox.Show(this, "Eine der Dateien existiert nicht", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); } |
Dies hab ich so übernommen, das einzige was ich geändert habe ist von Liste<Daten> auf Arraylist.
LG
CoolAce
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 19.08.08 21:38
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Di 19.08.08 22:31
hy,
hab ich übersehen und geändert , großes Sorry. Hab jetzt eine Parametrisierte Liste.
Trotzdem geht es irgendwie nicht mit
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| private void btnexit_Click(object sender, EventArgs e) {
using(FileStream fs = File.Create(@"E:\Butler\geburtstag.xml")) xs.Serialize(fs, liste); this.Close(); } |
LG
Coolace
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 19.08.08 22:38
Hm.  Zeig mal bitte Deine Daten-Klasse.
//edit: Ist Deine Klasse public? Das muss sie sein für den XMLSerializer!
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mi 20.08.08 20:27
Hy,
Sie war nicht public, hab Sie jetzt geändert aber er bringt immer noch den selben Fehler, hier nur die daten Klasse
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:
| public class daten { string gebname; DateTime gebdatum;
public string Gebname { get { return gebname; } set { gebname = value; } }
public DateTime Gebdatum { get { return gebdatum; } set { gebdatum = value; } }
public override string ToString() { string s = gebdatum.ToShortDateString() + " " + gebname; return s; }
public string Alter() { string age = Convert.ToString(DateTime.Now.Year - gebdatum.Year); return age; }
} } |
LG
Coolace
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 20.08.08 20:30
Häng mal bitte das gesamte Projekt an, ich sehe da im Moment keinen Fehler 
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mi 20.08.08 20:33
werden .zip Dateien freigeschalten oder soll ich es extern hochladen und den Link posten ?
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 20.08.08 20:37
zip-Dateien bis 2MB sind erlaubt.
(die Ordner "bin" und "obj" brauchst Du nicht mit einpacken)
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mi 20.08.08 20:39
Hy,
habs mal schnell auf nen hoster gelegt.
www.materialordner.d...OdPDoxyxdbKF2PG.html
Vielen Dank
Gruß
Coolace
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mi 20.08.08 20:44
Im Konstruktor des XMLSerializers verwendest Du noch ArrayList. Das passt dann nicht mit der List<daten> zusammen.
C#-Quelltext 1:
| XmlSerializer xs = new XmlSerializer(typeof(ArrayList)); |
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
coolace 
      
Beiträge: 141
|
Verfasst: Mi 20.08.08 20:51
das geht, isch werd verrückt, das geht
vielen vielen Dank für die Geduld. Nur noch ein kleinen Tipp bräuchte ich
ich will die Liste nach Datum sortieren, in der Arrayklasse brauch ich ja eine
IComparer Klasse dafür, brauch ich das hier auch ?
|
|