Pergunta

Eu estou tentando ligado um DataGridViewComboBoxColumn para uma instância de Foo, mas quando eu definir um valor no grid eu tenho um ArgumentException me dizendo que eu não posso converter de String para 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

Estou faltando alguma coisa? é possível vincular a um objeto complexo?

UPDATE:

Eu implementou um TypeConverter e overrided CanConvertFrom, CanConvertTo, ConvertTo, ConvertFrom. Agora eu estou recebendo

FormatException: O valor DataGridViewComboBoxCell não é válido

Todas as idéias?

Foi útil?

Solução

Está faltando uma possível peça.

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:

Na verdade, depois de ler a sua pergunta novamente, eu acho que você está enfrentando esse bug observou. Infelizmente, não há maneira de fazê-lo retornar o objeto vinculado sem usar um TypeDescriptor custom / TypeConverter / BindingSource.

Resposta para a ligação a um objeto complexo. Não por padrão. Eu escrevi bastante uma agradável para o meu projeto atual. Isso envolve a criação de um TypeDescriptor custom / TypeConverter / BindingSource que retorna todas as propriedades aninhadas. Outro 'bug', você não pode usar '' para um separador de membro, I teve de recorrer à ':' em vez

.

Outras dicas

o DataGridViewComboBoxColumn deve sempre ter todos os valores possíveis na lista de Itens combobox ou ele vai jogar. "FormatException: O valor DataGridViewComboBoxCell não é válido"

Se você está tentando voltar valores escolhidos a partir de uma coluna combobox, você pode manipular o evento DataGridView CellParsing, e obter o item selecionado da DataGridView.EditingControl porque isso será definido para controle de edição da coluna editada. Aqui é um 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;
   }
}

Você também pode personalizar a forma como os objetos são mostrados em cada célula por manipulação da célula formatação do evento, aqui é um código que toString exibição para qualquer objeto ou interface.

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

lida com esse dois eventos deve ser suficiente para mostrar e editar dados dentro de qualquer objeto bussiness e seu easer, em seguida, conversores de tipo de escrita. Para este trabalho fixado de DataGridView e você combobox coluna a seguir:

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

No DisplayMember ou necessidade ValueMember propriedade a ser definida, apenas certifique-se a sua lista de fonte de dados lista tem todos os valores possíveis para Foo.

Hope sua ajuda.

Na verdade, você pode usar um tipo complexo no DataGridViewComboBoxColumn.

Por exemplo:

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

Self é:

public ValueModeItem Self
{
    get
    {
        return this;
    }
}

Muito importante - a necessidade de substituir 'é igual a' método de um tipo complexo. No meu caso:

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

Eu estava constantely bater o mesmo problema até que eu viúva que você não pode definir o DisplayMember do DataGridViewComboBoxCell sem definir o ValueMember também.
Da mesma forma, a definição da ValueMember e não o DisplayMember é uma falha muito, você tem que definir nenhum ou ambos.

Seu modelo é Foo, e você certamente deseja que o valor do ComboBox ser o item em si. Para fazer isso, a maneira mais simples é também criar uma propriedade em sua foo, voltando-se.

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

ligações torna-se então:

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

Isso deve funcionar, eo valor da célula deve ser do tipo Foo como esperado.

Uma referência interessante: Problemas com o DataGridViewComboBoxColumn

No entanto, o DataGridViewComboBoxColumn não funciona assim, embora ele irá exibir o valor ToString se você não definir o DisplayMember, algo dá internamente errado quando se tenta olhar o SelectedItem, você tem que definir DisplayMember a um público propriedade de sua classe. Pior ainda, o comportamento padrão se você não faz definir a propriedade ValueMember é devolver o DisplayMember, há nenhuma maneira de obter item real em si. A única solução é adicionar um propriedade para sua classe que retorna-se e definir essa propriedade para o ValueMember. Claro, se o item não é algo que você é capaz a alteração (como uma das classes do framework) você terá que cludge juntos um objeto recipiente que contém uma referência ao seu item.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top