Wie man einen DataGridViewComboBoxColumn zu einem Objekt gebunden?
-
08-07-2019 - |
Frage
Ich versuche, eine DataGridViewComboBoxColumn
zu einer Instanz von Foo gebunden, aber wenn ich einen Wert auf dem Gitter gesetzt bekam ich einen ArgumentException
mir zu sagen, dass ich nicht von String in Foo umwandeln kann.
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
Bin ich etwas fehlt? ist es möglich, zu einem komplexen Objekt Databind?
UPDATE:
ich implementiert eine Typeconverter und overrided CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Jetzt bin immer i
Format: Der DataGridViewComboBoxCell Wert nicht gültig ist
Irgendwelche Ideen?
Lösung
Sie vermissen ein mögliches Stück.
column.DataPropertyName = "Foo";
column.DisplayMember = "SomeNameField";
column.ValueMember = "Bar"; // must do this, empty string causes it to be
// of type string, basically the display value
// probably a bug in .NET
column.DataSource = from foo in Foo select foo;
grid.DataSource = data;
UPDATE:
Eigentlich, nachdem Ihre Frage noch einmal zu lesen, ich glaube, Sie darauf hingewiesen, Fehler konfrontiert sind. Es gibt leider keine Möglichkeit, es das gebundene Objekt zu machen zurückgeben eine benutzerdefinierte TypeDescriptor / Typeconverter / Binding ohne Verwendung.
Antwort zu einem komplexen Objekt zu binden. Nein standardmäßig. Ich schrieb einen ganz nett für ein aktuelles Projekt. Dies beinhaltet das Herstellen einer benutzerdefinierten TypeDescriptor / Typeconverter / Binding, die alle verschachtelten Eigenschaften zurückgibt. Ein weiterer ‚Fehler‘, man kann verwenden ‚‘ Nach einem Mitglied Separator, musste ich greifen ‚:‘. statt
Andere Tipps
die DataGridViewComboBoxColumn sollten immer alle haben die möglichen Werte in der Combobox Liste Items oder es wird werfen. „Format: Der DataGridViewComboBoxCell Wert nicht gültig ist“
Wenn Sie versuchen, Werte von einer Combobox Spalte gewählt, um wieder, können Sie die Datagridview CellParsing Ereignis, Griff und das ausgewählte Element aus DataGridView.EditingControl bekommen weil es die Steuerung von dem bearbeiteten Spalte gesetzt wird für die Bearbeitung. Hier ist ein exemple:
private void dataGridView1_CellParsing(object sender,
DataGridViewCellParsingEventArgs e) {
if (dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn) {
DataGridViewComboBoxEditingControl editingControl =
(DataGridViewComboBoxEditingControl)dataGridView1.EditingControl;
e.Value = editingControl.SelectedItem;
e.ParsingApplied = true;
}
}
Sie können auch die Art und Weise anpassen können Ihre Objekte zeigen sind auf jeder Zelle, die durch die Zellformatierung Ereignisbehandlung, hier ist ein Code, den toString für jedes Objekt oder eine Schnittstelle angezeigt werden.
private void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e) {
if (e.Value != null) {
e.Value = e.Value.ToString();
e.FormattingApplied = true;
}
}
behandelt diese beiden Ereignisse sollten für die Show und Bearbeiten von Daten innerhalb eines bussiness-Objekt und seine easer dann Schreibtyp-Wandler genug sein. Für diese Arbeit, die Sie und Sie Datagridview combobox Spalte wie folgt festgelegt:
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList ();
Nein Display oder Valuemember Eigentum müssen eingestellt werden, nur sicherstellen, dass Ihre Combobox Datenquelle Liste, die alle möglichen Werte für Foo hat.
Hoffnung seine hilft.
Eigentlich kann man einen komplexen Typen in DataGridViewComboBoxColumn
verwenden.
Zum Beispiel:
DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);
Self
ist:
public ValueModeItem Self
{
get
{
return this;
}
}
Sehr wichtig - müssen außer Kraft setzen ‚Equals‘ Methode eines komplexen Typs. In meinem Fall:
public override bool Equals(object obj)
{
if (obj is ValueModeItem && obj != null)
{
if (...)
return true;
}
return false;
}
Ich schlug constantely das gleiche Problem, bis ich discovert, dass Sie nicht zu dem DisplayMember
der DataGridViewComboBoxCell
ohne Einstellung den ValueMember
einstellen.
In der gleichen Art und Weise, die ValueMember
Einstellung und nicht die DisplayMember
ist versagen, müssen Sie keine oder beides definieren.
Ihr Modell ist Foo, und Sie wollen sicher, dass der Wert des ComboBox das Element selbst sein. Für diese Weise ist der einfachste Weg, eine Immobilie in Ihrer foo zu schaffen, selbst zurück.
public class Foo
{
...
public Foo This { get {return this; } }
}
Dann Bindungen werden:
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
column.ValueMember = "This";
Das sollte funktionieren, und der Wert der Zelle soll vom Typ Foo sein wie erwartet.
Eine interessante Referenz: Probleme mit dem DataGridViewComboBoxColumn
Allerdings ist die DataGridViewComboBoxColumn nicht arbeiten, obwohl es den ToString Wert angezeigt, wenn Sie die nicht festlegen Display, geht etwas intern falsch, wenn er versucht zu suchen bis die SelectedItem, haben Sie Display zu einem öffentlichen einzustellen Eigenschaft Ihrer Klasse. Noch schlimmer ist, wenn das Standardverhalten nicht wahr setzen die Valuemember Eigenschaft ist die Display zurückzukehren, gibt es keine Möglichkeit, selbst tatsächlichen Einzelteil erhalten. Die einzige Arbeit, ist um ein hinzufügen Eigenschaft Ihrer Klasse, die sich selbst zurückkehrt und festgelegt, dass die Eigenschaft auf die Valuemember. Natürlich, wenn Ihr Artikel nicht etwas ist, sind Sie in der Lage (Wie zum Beispiel einer der Framework-Klassen) ändern müssen Sie werden cludge zusammen ein Containerobjekt, das einen Verweis auf Ihr Element hält.