0

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

  • One that creates clients ( can have multiple phones, addresses and cars)
  • A main form which should display each client info.

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

antonicelli
  • 333
  • 1
  • 4
  • 11
  • Why are you returning the row if the method adds it already (or vice versa if you want) ? Also, naming of vars is lacking. What is `Autos`? you use it as a `DataGridViewComboBoxCell ` (DGVCBC for short) and also as a property on your Cliente object? Can you post the Cliente code? – Noctis Nov 07 '13 at 05:14
  • Autos was just the name I wanted to give the combo I wanna add to my row, should name it DGVCBCAutos I guess – antonicelli Nov 07 '13 at 05:29
  • You should have, indeed :). Anyways, now you call your Client ctor with twice, and add some phones, addresses and cars, right? And then when you call the buildrow, it crashes I assume. Can you post the initialization code, or is it from a db? (so I can test it here). (and why altura and not numero for direccion??) – Noctis Nov 07 '13 at 05:37

2 Answers2

1

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" };
    }
}
Community
  • 1
  • 1
Noctis
  • 11,507
  • 3
  • 43
  • 82
  • Thanks, but my problem is that I need different datasources for different comboboxes, and the example in the blog only has one and it's for the whole column. Also I need to create a row with my client's data, and I don't know what argument to pass. – antonicelli Nov 07 '13 at 03:50
  • I already did that, the client class has 3 properties which are collections, (list , and
    ) still can't solve my problem.
    – antonicelli Nov 07 '13 at 05:08
1

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!

lauCosma
  • 154
  • 10