How to bind a collection of objects to a DataGridView in Winforms
Asked Answered
W

3

6

If i have two objects, namely Fruit' andColor` and their definitions are as follows:

public class Fruit  
{  
  public int FruitId { get; set; }  
  public string Name { get; set; }  
  public Color Color { get; set; }  
}  

public class Color  
{  
  public int ColorId { get; set; }  
  public string Name { get; set; }  
}  

How do I bind a collection of Fruit (e.g. List<Fruit>) to a DataGridView? where the resulting output would be something similar to the following:

+-----+--------+----------+  
| Id  | Name   | Color    |  
+-----+--------+----------+  
| 10  | Apple  | Red      |  
| 20  | Orange | Orange   |  
| 30  | Grapes | Violet   |  
+-----+--------+----------+  

and NOT like the following output below: (Note: the N in N.Color indicates the namespace of the object Color)

+-----+--------+------------+  
| Id  | Name   | Color      |  
+-----+--------+------------+  
| 10  | Apple  | N.Color    |  
| 20  | Orange | N.Color    |  
| 30  | Grapes | N.Color    |  
+-----+--------+------------+  

Update #1:
I found a similar post here on SO and tried some of the suggestion on that post but it's not working...

Woodwind answered 21/10, 2014 at 16:46 Comment(3)
Do you have a Color type property Color in your class Fruit, because then you will get the output N.Color, Also why your Name in Color class is of type int ?Why
Oh my bad, I forgot to change it to string. I'll edit it quickly.Woodwind
and yes, I have a Color type property in my class FruitWoodwind
W
5

Ok, after a couple of days figuring out how to make my app work I managed to find some article that helped me a lot in solving my problem. I thought I'd share it here on SO for you guys so lets start:

First, lets assume we already have a list of fruit stored in a variable fruits, and lets assume we already got it's value from a method:

List<Fruit> fruits = method();  

Now, my problem was... If I bind that list to a datagridview using the following command:

datagridview.DataSource = fruits;  

It will give me a result similar to the following:

+-----+--------+------------+  
| Id  | Name   | Color      |  
+-----+--------+------------+  
| 10  | Apple  | N.Color    |  
| 20  | Orange | N.Color    |  
| 30  | Grapes | N.Color    |  
+-----+--------+------------+   

Which is not what I want. So I thought maybe if I somehow put each columns to the datagridview manually, I could specify which properties from my fruits list to display. So I did something like this:

DataGridViewColumn col3 = new DataGridViewTextBoxColumn();  
col3.DataPropertyName = "Color.Name";  
col3.HeaderText = "Color Name";  
dataGridView1.Columns.Add(col3);  

But then, specifying something like this Color.Name on the DataPropertyName of the DataGridView column is not working, and will only result to a blank column with no data being displayed on the DataGridView. In order for it to work, the DataGridView should have a cell formatting function to properly display it's value in that given column. For the complete tutorial on how to do the formatting, you can check it out here from Antonio Bello's blog.

And that's it, hope it helps you too ^_^

Woodwind answered 23/10, 2014 at 7:18 Comment(2)
I suggest thisUnsparing
Just make a DisplayFruit object with a Fruit object delegate and implement the DisplayFruit properties however you want to make it display. Pretty much the answer given below, but without anonymity. Also allows you to modify properties of the underlying Fruit object if you want.Larynx
W
7

You have multiple options.

You can override ToString method in your Color class to return Name like:

public class Color
{
    public int ColorId { get; set; }
    public string Name { get; set; }
    public override string ToString()
    {
        return Name;
    }
}  

Or instead of assigningList<Fruit> as DataSource you can select a list of anonymous object and select Name of Color in your result like:

var result = yourListOfFruit
                .Select(r => new
                        {
                            FruitID = r.FruitId, 
                            Name = r.Name, 
                            Color = r.Color.Name,
                        }).ToList();

dataGridView1.DataSource = result;
Why answered 21/10, 2014 at 17:2 Comment(4)
I am trying to implement the concept from my question above in an MVP based application..if I override the ToString method of Color, then does that mean I can't use it's other proerties if it happens to have other properties than the ColorId and Name?...Woodwind
@devpro101, I missed the MVP tag, and I am not sure how that would work. Also overriding ToString would only effect the places where you would do objOfColorType.ToString(), you can still access all the properties of the object.Why
just a quick question, If I implement your second example using the anonymous object on the datagridview, will it still be able to listen for updates on the Fruit's properties when it changes?Woodwind
I am not sure what you meant by "listen" do you have an Observable Collection ?Why
W
5

Ok, after a couple of days figuring out how to make my app work I managed to find some article that helped me a lot in solving my problem. I thought I'd share it here on SO for you guys so lets start:

First, lets assume we already have a list of fruit stored in a variable fruits, and lets assume we already got it's value from a method:

List<Fruit> fruits = method();  

Now, my problem was... If I bind that list to a datagridview using the following command:

datagridview.DataSource = fruits;  

It will give me a result similar to the following:

+-----+--------+------------+  
| Id  | Name   | Color      |  
+-----+--------+------------+  
| 10  | Apple  | N.Color    |  
| 20  | Orange | N.Color    |  
| 30  | Grapes | N.Color    |  
+-----+--------+------------+   

Which is not what I want. So I thought maybe if I somehow put each columns to the datagridview manually, I could specify which properties from my fruits list to display. So I did something like this:

DataGridViewColumn col3 = new DataGridViewTextBoxColumn();  
col3.DataPropertyName = "Color.Name";  
col3.HeaderText = "Color Name";  
dataGridView1.Columns.Add(col3);  

But then, specifying something like this Color.Name on the DataPropertyName of the DataGridView column is not working, and will only result to a blank column with no data being displayed on the DataGridView. In order for it to work, the DataGridView should have a cell formatting function to properly display it's value in that given column. For the complete tutorial on how to do the formatting, you can check it out here from Antonio Bello's blog.

And that's it, hope it helps you too ^_^

Woodwind answered 23/10, 2014 at 7:18 Comment(2)
I suggest thisUnsparing
Just make a DisplayFruit object with a Fruit object delegate and implement the DisplayFruit properties however you want to make it display. Pretty much the answer given below, but without anonymity. Also allows you to modify properties of the underlying Fruit object if you want.Larynx
O
1

You can check this property DataGridView.DataSource Property

        // Automatically generate the DataGridView columns.
        dataGridView1.AutoGenerateColumns = true;

        // Set up the data source.
        bindingSource1.DataSource = GetData("Select * From Products");
Openwork answered 21/10, 2014 at 16:54 Comment(1)
I already done that kind of process (not exactly but it's similar)... what I'm trying to do now is to generate a collection of an object say a List<Fruit> and then use it somehow for a datagridview...Woodwind

© 2022 - 2024 — McMap. All rights reserved.