antonicelli
antonicelli

Reputation: 333

Add DataGridViewComboBoxCell with different data sources to a DataGridView

I've already checked other posts but still could not fix my probem: I have two forms:

enter image description here

First of all, is it possible to have a client in each row, and the three combos (phones, addresses, and cars) with each clients info?

For example:

I've got two clients, John and Jack, and I want the rows displayed like this:

0 - John - John.Phones - John.Addresses - John.Cars
1 - Jack - Jack.Phones - Jack.Addresses - Jack.Cars

Also, I don't know what should I pass to my row as argument for the combobox, should I pass the dataSource, Items, or the combo itself? Whatever I pass for the comboboxes, I get: System.ArgumentException: DatagridViewRowComboBoxCell value is not valid

Here's the actual code.

private DataGridViewRow BuildRow(Cliente cliente)
{
    DataGridViewRow row = new DataGridViewRow();           
    DataGridViewComboBoxCell Autos = new DataGridViewComboBoxCell();


    Autos.DataSource = cliente.Autos;
    Autos.ValueMember = cliente.Autos[0].ToString();
    row.CreateCells(DGCliente, cliente.Codigo.ToString(), cliente.Nombre, Autos);
    row.Tag = cliente;
    DGCliente.Rows.Add(row);

    return row;
}

Client class code: (spanish)

public class Cliente
{
    public String Nombre { get; set; }
    public Int32 Codigo { get; set; }
    public List<Auto> Autos { get; set; }
    public List<Direccion> Direcciones { get; set; }
    public List<Telefono> Telefonos { get; set; }

    public Cliente()
    {
        this.Direcciones = new List<Direccion>();
        this.Telefonos = new List<Telefono>();
        this.Autos = new List<Auto>();

    }

    public Cliente(String Nombre , Int32 Codigo)
    {
        this.Nombre = Nombre;
        this.Codigo = Codigo;
        this.Direcciones = new List<Direccion>();
        this.Telefonos = new List<Telefono>();
        this.Autos = new List<Auto>();
    }

    public void AgregarTelefono(bool esCelular, String numero, String area)
    { 
       this.Telefonos.Add(new Telefono(esCelular, numero, area));
    }

    public void AgregarDireccion(string calle, string altura, string localidad, string provincia)
    {
        this.Direcciones.Add(new Direccion(calle, altura, localidad, provincia));
    }

    public void AgregarAuto(Auto auto)
    {
        this.Autos.Add(auto);
    }
}

Upvotes: 0

Views: 3788

Answers (2)

lauCosma
lauCosma

Reputation: 154

You can create a row for every client with 2 types of cell a textbox cell and a combobox cell. Consider the following :

 public class PersonRow : DataGridViewRow
    {
        public DataGridViewTextBoxCell Name;
        public DataGridViewComboBoxCell Phones;
        public DataGridViewComboBoxCell Cars;

        public PersonRow(Person person)
        {
            Name.Value = person.Name;

            DataGridViewComboBoxCell phones = new DataGridViewComboBoxCell();
            phones.Items.AddRange((DataGridViewComboBoxCell.ObjectCollection)person.Phones); //add the items from Person.Phones to PersonRow.Phones combobox cell

            Phones = phones;

            DataGridViewComboBoxCell cars = new DataGridViewComboBoxCell();
            cars.Items.AddRange((DataGridViewComboBoxCell.ObjectCollection)person.Cars); //add Person.Cars to PersonRow.Cars combobox cell 

            Cars = cars;

            Cells.AddRange(new DataGridViewCell[] { Name, Phones, Cars }); //add cells to the row

        }
    }

public class Person
    {
        public string Name { get; set; }

        public IList<Phones>  Phones { get; set; } //be sure to use the IList interface
        public IList<Cars> Cars { get; set; } //be sure to implement the IList interface

        public Person( string name, List<Phones> phones, List<Cars> cars)
        {
            Name = name;
            Phones = phones;
            Cars = cars;
        }
    }

public class Phones
    {
        public string Name { get; set; }
        public string Model { get; set; }

        public Phones(string name, string model)
        {
            Name = name;
            Model = model;

        }
    }

    public class Cars
    {
        public string Name { get; set; }
        public string Model { get; set; }

        public Cars(string name, string model)
        {
            Name = name;
            Model = model;
        }
    }

Also checkout :http://msdn.microsoft.com/en-us/library/bc3sctb6(v=vs.110).aspx and http://msdn.microsoft.com/en-us/library/system.windows.forms.combobox.objectcollection.aspx and http://msdn.microsoft.com/en-us/library/system.collections.ilist(v=vs.110).aspx Hope this helps!

Upvotes: 1

Noctis
Noctis

Reputation: 11763

Regarding your first question. Of course you can. You can look here, or at any other StackOverflow with that tag.

The real problem is the how. Most of the posts are WPF related, in which case the binding would have helped, but I highly suggest having a read through this guy's blog where he's having an example with code for a similar result.

Suerte :)

Edit:
Your DataGridViewComboBoxCell source should be an IList or IListSource that contains a collection of values used to supply data to the drop-down list (look here if you don't believe me).

So, each of your objects should have a property which is a List or whatever you would like that satisfies the IList interface, and you should bind that to your source.

So, for example, if the following class is your object, you should bind that object to the row, but specifically BindToThis1 (&2) to your DataGridViewComboBoxCell sources (like he did in the example with dtTitles).

public class MyObject
{
    public List<string> BindToThis1 { get; set; }
    public List<string> BindToThis2 { get; set; }

    public MyObject()
    {
        BindToThis1 = new List<string> { "hello", "world" };
        BindToThis2 = new List<string> { "red", "blue", "green" };
    }
}

Upvotes: 1

Related Questions