2009-03-10 13 views
4

Ich versuche, eine DataGridViewComboBoxColumn an eine Instanz von Foo zu binden, aber wenn ich einen Wert auf das Raster gesetzt habe ich eine ArgumentException sagte mir, dass ich nicht von String zu Foo konvertieren kann.Wie bindet man eine DataGridViewComboBoxColumn an ​​ein Objekt?

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 

Fehle ich etwas? Ist es möglich, an ein komplexes Objekt zu binden?

UPDATE:

implementiert ich einen Typeconverter und overrided CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Jetzt bin ich immer

Format: Der DataGridViewComboBoxCell Wert ist nicht gültig

Irgendwelche Ideen?

Antwort

6

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 nach wieder Ihre Frage zu lesen, ich glaube, Sie darauf hingewiesen, Fehler konfrontiert sind. Es gibt leider keine Möglichkeit, das gebundene Objekt zurückzugeben, ohne einen benutzerdefinierten TypeDescriptor/TypeConverter/BindingSource zu verwenden.

Antwort für die Bindung an ein komplexes Objekt. Nein standardmäßig. Ich habe für mein aktuelles Projekt ein ganz schönes geschrieben. Dies beinhaltet die Erstellung eines benutzerdefinierten TypeDescriptor/TypeConverter/BindingSource, der alle verschachtelten Eigenschaften zurückgibt. Ein weiterer "Bug", den du nicht benutzen kannst. Für ein Member-Trennzeichen musste ich stattdessen auf ":" zurückgreifen.

+0

Wie mache ich den TypeConverter? – albertein

+0

Sie erben von TypeConverter und überschreiben die GetProperties/GetPropertiesSupported-Methoden. Wenden Sie dann den Typ auf das TypeConverterAttribute auf Ihrem gewünschten Zieltyp an. Das Themengebiet ist sehr groß. Google für etwas mehr Richtung. – leppie

+0

Ich implementierte einen TypeConverter und überschrieb CanConvertTo, CanConvertFrom, ConvertTo und ConvertFrom, jetzt bekomme ich den Fehler "FormatException: Der Wert der DataGridViewComboBoxCell ist nicht gültig" nach dem Setzen des Wertes – albertein

6

Die DataGridViewComboBoxColumn sollte immer alle möglichen Werte in der Combobox Elementliste haben oder es wird "FormatException: Der DataGridViewComboBoxCell Wert ist nicht gültig".

Wenn Sie versuchen, Werte aus einer Combobox-Spalte zurückzugewinnen, können Sie das DataGridView CellParsing-Ereignis behandeln und das ausgewählte Element aus DataGridView.EditingControl abrufen, da es für das Bearbeiten der Steuerung aus der bearbeiteten Spalte festgelegt wird. 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 Ihre Objekte sind zeigen auf jeder Zelle, die durch die Zellformatierung Ereignisbehandlung, hier ist ein Code, der toString für jedes Objekt oder eine Schnittstelle anzuzeigen.

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(); 

Keine Display oder Valuemember Eigentum müssen eingestellt werden, so stellen Sie sicher, dass Ihre Combobox Datenquelle Liste, die alle möglichen Werte für Foo hat.

Hoffe, es hilft.

+0

Erstaunlich! Vielen Dank!!!! –

+0

Komisch, das ist das Einzige, was mir die Aufgabe gemacht hat und gleichzeitig das Einfachste. Ich kann nicht sehen, wie es nur 4 Stimmen bekam und war schwer zu finden. Jede Idee, warum die Standardimplementierung versucht, die Zeichenfolgendarstellung des ausgewählten Elements in den Typ der Datenquelle zu konvertieren (was bei benutzerdefinierten Typen fehlschlägt und schwer mit einem benutzerdefinierten Konverter anzupassen ist), anstatt nur das ausgewählte Element (das verfügbar ist) festzulegen !), wie die Standard-Combobox? –

2

Ich habe constantely das gleiche Problem treffen, bis ich entdeck, dass Sie die DisplayMember der DataGridViewComboBoxCell nicht setzen können, ohne die ValueMember auch zu setzen.
In der gleichen Weise, die Einstellung ValueMember und nicht die DisplayMember ist auch ein Fehler, müssen Sie keine oder beide definieren.

Ihr Modell ist Foo, und Sie möchten sicherlich, dass der Wert der ComboBox das Element selbst ist. Um dies zu tun, ist der einfachste Weg, eine Eigenschaft in Ihrem foo zu erstellen, die sich selbst zurückgibt.

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"; 

Dies sollte funktionieren, und der Wert der Zelle soll vom Typ Foo sein wie erwartet.

Eine interessante Referenz: Problems with the DataGridViewComboBoxColumn

Allerdings ist die DataGridViewComboBoxColumn nicht arbeiten, obwohl es wird die ToString Wert angezeigt, wenn die Display nicht gesetzt ist, geht etwas intern falsch, wenn es versucht, bis SelectedItem zu suchen, müssen Sie DisplayMember auf eine öffentliche Eigenschaft Ihrer Klasse festlegen. Schlimmer noch, das Standardverhalten, wenn Sie nicht die setzen die ValueMember-Eigenschaft ist, um das DisplayMember zurückgeben, gibt es keine Möglichkeit, tatsächliche Element selbst zu erhalten. Die einzige Umgehung ist das Hinzufügen einer -Eigenschaft zu Ihrer Klasse, die sich selbst zurückgibt und diese Eigenschaft auf ValueMember setzt. Natürlich, wenn Ihr Artikel nicht etwas ist, das Sie ändern können (zB eine der Framework-Klassen), müssen Sie zusammen ein Container-Objekt, das einen Verweis auf Ihr Element enthält.

4

tatsächlich können Sie einen komplexen Typ in DataGridViewComboBoxColumn verwenden. EX:

 DataGridViewComboBoxColumn.DataPropertyName = "ValueMode"; 
     DataGridViewComboBoxColumn.DisplayMember = "Label"; 
     DataGridViewComboBoxColumn.ValueMember = "Self"; * 
     DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem); 
  • 'Self' ist
public ValueModeItem Self 
    { 
     get 
     { 
      return this; 
     } 
    } 

und sehr wichtig - müssen 'Equals' Methode eines komplexen Typs außer Kraft zu setzen - in meinem Fall:

public override bool Equals(object obj) 
    { 
     if (obj is ValueModeItem && obj != null) 
     { 
      if (...) 
       return true; 
     } 
     return false; 
    } 
Verwandte Themen