Domanda

Sto cercando di associare un DataGridViewComboBoxColumn a un'istanza di Foo, ma quando ho impostato un valore sulla griglia ho ricevuto un ArgumentException che mi dice che non posso convertire da String a Foo.

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

Mi sto perdendo qualcosa? è possibile associare un database a un oggetto complesso?

UPDATE:

Ho implementato un TypeConverter e ho ignorato CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Ora sto ricevendo

  

FormatException: il valore DataGridViewComboBoxCell non è valido

Qualche idea?

È stato utile?

Soluzione

Ti manca un possibile pezzo.

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:

In realtà, dopo aver letto di nuovo la tua domanda, penso che stai affrontando quel bug notato. Sfortunatamente non c'è modo di farlo restituire l'oggetto associato senza usare un TypeDescriptor / TypeConverter / BindingSource personalizzato.

Rispondi per l'associazione a un oggetto complesso. No per impostazione predefinita. Ne ho scritto uno abbastanza carino per il mio progetto attuale. Ciò comporta la creazione di un TypeDescriptor / TypeConverter / BindingSource personalizzato che restituisce tutte le proprietà nidificate. Un altro "bug", non puoi usare "." per un separatore membro, ho dovuto ricorrere a ':' invece.

Altri suggerimenti

DataGridViewComboBoxColumn dovrebbe sempre avere tutti i possibili valori nell'elenco degli elementi della casella combinata o genererà " FormatException: il valore DataGridViewComboBoxCell non è valido " ;.

Se stai cercando di recuperare i valori scelti da una colonna della casella combinata, puoi gestire l'evento CellGrars di DataGridView e ottenere l'elemento selezionato da DataGridView.EditingControl perché verrà impostato per il controllo di modifica dalla colonna modificata. Ecco un esempio:

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

Puoi anche personalizzare il modo in cui i tuoi oggetti sono mostrati su ogni cella gestendo l'evento Formatting della cella, ecco un codice che mostra a String per qualsiasi oggetto o interfaccia.

private void dataGridView1_CellFormatting(object sender, 
    DataGridViewCellFormattingEventArgs e) {
        if (e.Value != null) {
            e.Value = e.Value.ToString();
            e.FormattingApplied = true;
        }
    } 

Gestisce questi due eventi dovrebbe essere sufficiente per mostrare e modificare i dati all'interno di qualsiasi oggetto bussiness ed è più semplice scrivere convertitori di tipi. Per questo lavoro impostare DataGridView e la colonna della casella combinata come segue:

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

Non è necessario impostare alcuna proprietà DisplayMember o ValueMember, assicurati solo che l'elenco delle origini dati combobox abbia tutti i valori possibili per Foo.

Spero che sia d'aiuto.

In realtà, puoi usare un tipo complesso in DataGridViewComboBoxColumn .

Ad esempio:

DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);

Self è:

public ValueModeItem Self
{
    get
    {
        return this;
    }
}

Molto importante: è necessario sostituire il metodo "Uguali" di un tipo complesso. Nel mio caso:

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

Ho costantemente riscontrato lo stesso problema fino a quando non ho scoperto che non è possibile impostare il DisplayMember del DataGridViewComboBoxCell senza impostare anche il ValueMember . < br> Allo stesso modo, l'impostazione del ValueMember e non del DisplayMember non è riuscita, è necessario definire nessuno o entrambi.

Il tuo modello è Foo e sicuramente desideri che il valore di ComboBox sia l'elemento stesso. Per fare questo, il modo più semplice è anche creare una proprietà nel tuo foo, restituendo se stessa.

public class Foo
{
    ...
    public Foo This { get {return this; } }
}

Quindi i binding diventano:

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

Questo dovrebbe funzionare e il valore della cella dovrebbe essere del tipo Foo come previsto.

Un riferimento interessante: Problemi con DataGridViewComboBoxColumn

  

Tuttavia, DataGridViewComboBoxColumn non funziona in questo modo,   sebbene visualizzerà il valore ToString se non si imposta   DisplayMember, qualcosa va storto internamente quando cerca di apparire   su SelectedItem, devi impostare DisplayMember su un pubblico   proprietà della tua classe. Ancora peggio, il comportamento predefinito se non lo fai   impostare la proprietà ValueMember è di restituire DisplayMember, c'è   nessun modo di ottenere l'oggetto reale stesso. L'unica soluzione è aggiungere a   proprietà della classe che restituisce se stessa e imposta tale proprietà su   ValueMember. Certo, se il tuo articolo non è qualcosa che puoi   per cambiare (come una delle classi del framework) dovrai rannicchiarti   insieme un oggetto contenitore che contiene un riferimento al tuo articolo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top