Fragensteller
Combobox SelectedIndexChanged Event in DataGridView

Allgemeine Diskussion
-
Hallo Experten,
ich habe wieder ein Problem, wo ich keine Lösung finde.
Ich habe ein Datagridview welches diverse Spalten enthält. Ein Spalte beinhaltet eine Combobox. Wird dort der Wert geändert möchte ich mit dem neuen Wert Änderungen in derselben Zeile, in welcher die Combobox geändert wurde, durchführen. Ich habe gegoogelt und einen Lösungsvorschlag gefunden, welcher aber bei mir aus irgend einem Grund nicht funktioniert.
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridvieweditingcontrolshowingeventargs.control%28v=vs.110%29.aspx
Mein Code sieht so aus:
private void bestellungDispositionDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cmb = e.Control as ComboBox; if (cmb != null) { cmb.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged); cmb.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged); } } private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { bestellungDispositionDataGridView.EndEdit(); int row = bestellungDispositionDataGridView.CurrentRow.Index; BestellungDisposition bestdispo = (BestellungDisposition)bestellungDispositionDataGridView.Rows[row].DataBoundItem; if (bestdispo.Traktionsmittel == "LKW") { Warenpos_Fracht_Berechnen(bestdispo); Warenpos_BerechneSummen(bestdispo, row); Warenpos_Summen_Anzeigen(); } else if (bestdispo.Traktionsmittel == "Waggon") { Warenpos_Fracht_Berechnen(bestdispo); Warenpos_BerechneSummen(bestdispo, row); Warenpos_Summen_Anzeigen(); } }
ComboBox_SelectedIndexChanged(object sender, EventArgs e) wird korrekt aufgerufen sobald der Wert in der Comboboxspalte geändert wird. Leider enthält die Combobox.Selectedvalue (oder der Wert in der Datagridview Spalte) immer noch den alten Wert. Versuche ich eine weitere Auswahl, bekomme ich den Wert null zurück.
Das Endedit() in meinem Datagridview habe ich hinzugefügt, das Resultat ist aber das selbe.
Ich hoffe, jemand weiß was hier falsch läuft.
Grüße, Siegfried
- Typ geändert Ciprian Bogdan Montag, 3. Februar 2014 17:25 keine Rückmeldung des Fragestellenden
Alle Antworten
-
Hallo,
die Änderung des Werts im DataGridView findet erst nach dem SelectedIndexChanged-Event statt. Du kannst aber aus dem sender-Parameter die ComboBox casten, welche die Änderung schon erhalten hat:private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { ComboBox cb = sender as ComboBox; if (cb != null) { Debug.WriteLine(cb.SelectedItem);//Das neu ausgewählte Item in die Ausgabe schreiben } }
Die jetzt markierte Zeile erhälst du von der CurrentCellAddress-Eigenschaft:dataGridView1.Rows[dataGridView1.CurrentCellAddress.Y].Cells[1].Value = cb.SelectedItem;
//Textbox in 2. Spalte den ausgewählten Wert der ersten Spalte zuweisenKoopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hallo Tom,
erstmal danke für die Hilfe, ich bekomme damit den eben selectierten Wert. Wenn ich keine weiteren Aktionen ausführe funktioniert das. Ich muss aber mit dem eben selektierten Wert die Fracht neu berechnen und diese muss in der selben Zeile des DGV angezeigt werden. Das wird in den 3 Methoden durchgeführt dich in anschließend aufrufe.
Sobald ich aber am Bindingsource des DGV eine Änderung vornehme, funktioniert es nicht mehr richtig. ComboBox_SelectedIndexChanged(object sender, EventArgs e) wird dann wiederholt aufgerufen und enthält keine gültigen Wert mehr (sondern z.B. null oder 'DispoModel.Waggon'). Wenn ich nur die Berechnungen durchführe aber keine Änderungen am DGV Datasource durchführe, wird ComboBox_SelectedIndexChanged(object sender, EventArgs e) korrekt nur einmal aufgerufen.
Ich bräuchte dringend eine Lösung, hat jemand eine Idee?
Gruß
Siegfried
- Bearbeitet Siegfried Reichmann Dienstag, 21. Januar 2014 16:18
-
Hallo,
ohne es jetzt getestet zu haben, kannst du am Anfang der SelectedIndexChanged eine Variable setzen (true) und am Ende der Methode wieder zurück setzen (false). Den neuen Wert verarbeitest du nur, wenn die Variable auf false steht.Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
/// <summary> /// Testet ob DataGridViewCheckBoxColumn.TrueValue =="True" (dieser Wert wurde manuell im Entwurf gesetzt) /// und setzt dann DataGridViewCheckBoxColumn.Value auf bool true oder false /// // FalseFalue = False /// // TrueValue = True /// // ReadOnly = False /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (((DataGridView)sender).CurrentCell.OwningColumn is DataGridViewCheckBoxColumn) { dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); string Checked = dataGridView1.CurrentCell.Value.ToString(); // hat tatsächlich den Wert von TrueValue if (Checked == "True") { dataGridView1.CurrentCell.Value = true; } else { dataGridView1.CurrentCell.Value = false; } } }
-
Hallo,
Bin schon etwas wirr im Kopf, habe übersehen, dass obige Nachrichten zwei Nachrichten sind. Habe aber beides probiert.
Es ist aber exakt das selbe Ergebnis. CurrentCellDirtyStateChecked(...) wird erst aufgerufen, nachdem Combobox_SelectedIndexChanged(...) schon 3 x aufgerufen wurde. Ich habe für den Test eine ungebundene Checkboxspalte in mein DGV eingefügt.
Gruß
Siegfried
- Bearbeitet Siegfried Reichmann Dienstag, 21. Januar 2014 20:12
-
Ich habe mal weiter probiert. Es gab keine Probleme, wenn ich direkt die Quelle veränderte und das Control sich aktualisieren ließ:
l[DataGridView1.CurrentCellAddress.Y].Col1 = (sender as ComboBox).SelectedItem.ToString(); DataGridView1.Refresh();
l ist eine List<Data> mit meinen Daten.
Eine Änderung direkt im DataGridView brachte auch keinen Erfolg.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hallo Siegfried,
Hast Du eigentlich Dein Problem gelöst ?
Funktioniert jetzt alles ?
Viele Grüße,
Ciprian
Ciprian Bogdan, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.
-
Hallo,
nein Problem nicht gelöst, habe mir eben ein kleines Testprogramm gemacht, irgendwo mache ich einen Fehler. Wenn ich in den zugrunde liegenden Daten etwas änder bekomme ich folgende Ausnahme:
DataGridView-Ausnahme:
System.ArgumentException: Die Items-Auflistung kann nicht geändert werden, wenn die DataSource-Eigenschaft festgelegt ist.
Ich poste hier einmal den kompletten Code dieses Beispielprogramms. Vorher habe ich es auch mit dem Beispielprogramm probiert, dass ich die Daten des DGV geändert habe, so wie ich es zuerst gemacht habe. Hier wird aber wie schon vorher Combobox_SelectedIndexChanged() mehrmals hinereinander aufgerufen, die übergebenen Werte der Combobox (SelectedValue) ändern sich bei jedem Aufruf.
Ich habe absichtlich im Code das erste Element geändert, der Fehler tritt auch nur auf, wenn ich die Combobox dieses Satzes ändere, wenn ich die Combobox eines anderen Satzes ändere, werden die Änderungen korrekt in der 1. Zeile eingetragen und es kommt auch keine Fehlermeldung.
Viele Grüße
Siegfried
using System; using System.Collections.Generic; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using DISPOModel; namespace Test { public partial class DGV_CMB : Form { DISPOEntities context = new DISPOEntities(); List<BestellungDisposition> _bestdisp; public DGV_CMB() { InitializeComponent(); } private void DGV_CMB_Shown(object sender, EventArgs e) { var waggons = context.Waggons.ToList(); DataGridViewComboBoxColumn dgvcmb = (DataGridViewComboBoxColumn)bestellungDispositionsDataGridView.Columns[getGridViewColIndex(bestellungDispositionsDataGridView, "Traktionsmittel2")]; dgvcmb.ValueMember = "Kurzbezeichnung"; dgvcmb.DisplayMember = "Kurzbezeichnung"; dgvcmb.DataSource = waggons; _bestdisp = context.BestellungDispositions.ToList(); bestellungDispositionsBindingSource.DataSource = _bestdisp; } private Int32 getGridViewColIndex(DataGridView dgv, string colbez) { int colindex = 0; for (int i = 0; i < dgv.Columns.Count; i++) { if (dgv.Columns[i].DataPropertyName == colbez) { colindex = i; break; } } return colindex; } private string getCellValue(DataGridView dgv, int row, string colname) { string returnvalue = ""; for (int i = 0; i < dgv.Columns.Count; i++) { if (dgv.Columns[i].DataPropertyName == colname) { returnvalue = dgv[i, row].Value.ToString(); } } return returnvalue; } private void bestellungDispositionDataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (((DataGridView)sender).CurrentCell.OwningColumn is DataGridViewCheckBoxColumn) { bestellungDispositionsDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); string Checked = bestellungDispositionsDataGridView.CurrentCell.Value.ToString(); // hat tatsächlich den Wert von TrueValue if (Checked == "True") { bestellungDispositionsDataGridView.CurrentCell.Value = true; } else { bestellungDispositionsDataGridView.CurrentCell.Value = false; } } } private void ComboBox_SelectedIndexChanged(object sender, EventArgs e) { { ComboBox cmb = sender as ComboBox; if (cmb != null) { if (cmb.SelectedValue == null) { return; } // bestellungDispositionDataGridView.Rows[bestellungDispositionDataGridView.CurrentCellAddress.Y].Cells[1].Value = "Test"; // bestellungDispositionDataGridView.Rows[bestellungDispositionDataGridView.CurrentCellAddress.Y].Cells[1].Value = cmb.SelectedValue; // bestellungDispositionDataGridView.EndEdit(); int row = bestellungDispositionsDataGridView.CurrentRow.Index; BestellungDisposition dsp = _bestdisp.FirstOrDefault(); dsp.VerfuegbareMengeTag = 0; dsp.LieferantName = "????"; } } } private void bestellungDispositionDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { ComboBox cmb = e.Control as ComboBox; if (cmb != null) { cmb.SelectedIndexChanged -= new EventHandler(ComboBox_SelectedIndexChanged); cmb.SelectedIndexChanged += new EventHandler(ComboBox_SelectedIndexChanged); } } } }
-
Hallo,
ich habe mir deinen Code eben nochmal angesehen. Ich verstehe dabei die ComboBox_SelectedIndexChanged-Methode nicht so ganz. FirstOrDefault wird im Normalfall immer den ersten Datensatz zurück geben. Du kannst auch einfach den einzelnen Datensatz abändern:int row = bestellungDispositionsDataGridView.CurrentRow.Index; _bestdisp[row].LieferantName = "???"; bestellungDispositionsDataGridView.Refresh();//Wert1 neu von DataSource einlesen
Ich habe zu testen den von dir geposteten Code in ein neues C# WinForms Projekt eingebaut. Dort funktionierte alles.
Wenn du noch weitere Hilfe brauchst, müsste ich (bzw. Andere) das Projekt mal im ganzen sehen, falls es noch mehr Unterschiede gibt. Entweder du postest es mal auf SkyDrive oder schickst es mir an koopakiller
live.de (wenn es kein anderer sehen soll).
PS: Spalten kannst du auch direkt anhand des Namens auswählen. Eine Hilfsmethode brauchst du dafür nicht:
DataGridViewComboBoxColumn dgvcmb = (DataGridViewComboBoxColumn)bestellungDispositionsDataGridView.Columns["Traktionsmittel2"];
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hallo Tom,
das FirstOrDefault() habe ich nur zum Testen verwendet um den 1. Datensatz im DGV zu verändern. Damit konnte ich feststellen, dass dieses Verhalten nur auftritt, wenn ich in der CurrentRow Daten verändere.
Ich habe es jetzt aus Zeitgründen vorübergehend anders gelöst. (Combobox ausserhalb des DGV). Wurde jetzt einmal akzeptiert, ich werde mich nochmals damit befassen, sobald ich mehr Zeit habe.
Vielen Dank erstmals, ich melde mich dann ggf. wieder
Siegfried
-
*****************************************************************************************************
Dieser Thread wurde mangels bestätigter Lösung abgeschlossen.
Neue Rückfragen oder Ergänzungen zu diesem Thread bleiben weiterhin möglich.
*****************************************************************************************************
Ciprian Bogdan, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip„Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.