Entwickler-Ecke
WinForms - ArrayList in Listbox kopieren
coolace - So 17.08.08 16:29
Titel: ArrayList in Listbox kopieren
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. - 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 ;-)
coolace - 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 - 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. - 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 :nixweiss:
//edit: Und jetzt benutze doch endlich List<Daten>! Dann kann sowas gar nicht passieren! ArrayList ist ALT und TOT für neue Projekte!
coolace - Mo 18.08.08 22:22
Sorry,
hier mein komplettes Programm
Hauptprogramm
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: 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. - 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 [
http://www.c-sharp-forum.de/help_schreiben_bbcodes_source.html&sub=,19,27,32] die Erklärung dazu.
coolace - 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. - 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.
coolace - 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. - Di 19.08.08 21:38
coolace hat folgendes geschrieben: |
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(ArrayList, fs); this.Close(); } | |
Das kompiliert? ArrayList ist doch eine Klasse und keine Instanz.
coolace hat folgendes geschrieben: |
| das einzige was ich geändert habe ist von Liste<Daten> auf Arraylist. |
Du bist echt beratungs-resistent. Jetzt mal konkret: Warum benutzt Du die ArrayList anstatt der List<T>-Klasse?
coolace - 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. - Di 19.08.08 22:38
Hm. :gruebel: Zeig mal bitte Deine Daten-Klasse.
//edit: Ist Deine Klasse public? Das muss sie sein für den XMLSerializer!
coolace - 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
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: 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. - Mi 20.08.08 20:30
Häng mal bitte das gesamte Projekt an, ich sehe da im Moment keinen Fehler :nixweiss:
coolace - Mi 20.08.08 20:33
werden .zip Dateien freigeschalten oder soll ich es extern hochladen und den Link posten ?
Christian S. - Mi 20.08.08 20:37
zip-Dateien bis 2MB sind erlaubt.
(die Ordner "bin" und "obj" brauchst Du nicht mit einpacken)
Christian S. - 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)); |
coolace - 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 ?
Christian S. - Mi 20.08.08 20:58
Du hast verschiedene Möglichkeiten die Sort-Methode der Liste zu verwenden.
- Du kannst in der daten-Klasse das IComparable-Interface implementieren und Sort ohne Parameter aufrufen
- Oder Du kannst eine Comparison<daten>-Methode implementieren, z.B. mit einer anonymen Methode:
C#-Quelltext
1:
| liste.Sort(delegate(daten x, daten y) { return x.Gebdatum.CompareTo(y.Gebdatum); }); |
Wenn Du C# 3.5 benutzt, kannst Du auch einen Lambda-Ausdruck bentuzen:
C#-Quelltext
1:
| liste.Sort((x, y) => x.Gebdatum.CompareTo(y.Gebdatum)); |
lothi - Mi 20.08.08 21:02
Hallo coolace
Es gibt da ein List<T>.Sort
edit:
zu spät
Gruss Lothi
coolace - Do 21.08.08 21:34
Hy,
dankeschön, das letzte Problem was ich noch hab ist das ich den Markierten Eintrag zwar von der listbox mit
listbox.Items.RemoveAt(listbox.SelectedIndex) löschen kann aber wenn ich den selben index mittels
liste.RemovAt(listbox.SelectedIndex) übergebe geht es nicht weil er einen negativen Index -1 zurückbekommt.
Wie bekomm ich das hin das er das aus meiner liste sauber rauslöscht ?
Christian S. - Do 21.08.08 21:38
Eigentlich gilt "Neue Frage -> Neuer Thread".
Aber wenn Du den selektierten Eintrag aus einer Listbox löschst, ist nix mehr selektiert, also ist danach SelectedIndex = -1.
Lösche erst aus der liste, dann aus der Listbox.
coolace - Do 21.08.08 21:48
ok vielen Dank
LG
Coolace
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!