This tutorial is kind of a follow-up to my previous tutorial about binding a DataGridView to an Access database. In this tutorial, I'm going to demonstrate how to bind a DataGridView to a regular old .NET collection.
Before we can build a collection of objects, we first need an object. I tend to use a Car object for most of my examples. The car object simply holds some information about a typical car - make, model, and year. Below is the object I'm going to use.
public class Car
{
private string _make;
private string _model;
private int _year;
public Car(string make, string model, int year)
{
_make = make;
_model = model;
_year = year;
}
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int Year
{
get { return _year; }
set { _year = value; }
}
}
All right, now that we've got an object, we need a collection to hold
them. One of my favorite collection objects is the List, located in
the System.Collections.Generic namespace, so we'll start with that.
List<Car> cars = new List<Car>();
cars.Add(new Car("Ford", "Mustang", 1967));
cars.Add(new Car("Shelby AC", "Cobra", 1965));
cars.Add(new Car("Chevrolet", "Corvette Sting Ray", 1965));
Binding this to a DataGridView is painfully easy. Simply set the DataSource property of the DataGridView to the List.
_dgCars.DataSource = cars;
What will happen is that the DataGridView will automatically create
columns for each property in the Car object, then create a row for each
Car in the List. What we've created here is one-way binding. Any changes
made by the user in the DataGridView will also take place in the List.
If we want changes made to a Car to update the DataGridView, the Car
object will have to implement the INotifyPropertyChanged interface.
public class Car : INotifyPropertyChanged
{
private string _make;
private string _model;
private int _year;
public event PropertyChangedEventHandler PropertyChanged;
public Car(string make, string model, int year)
{
_make = make;
_model = model;
_year = year;
}
public string Make
{
get { return _make; }
set
{
_make = value;
this.NotifyPropertyChanged("Make");
}
}
public string Model
{
get { return _model; }
set
{
_model = value;
this.NotifyPropertyChanged("Model");
}
}
public int Year
{
get { return _year; }
set
{
_year = value;
this.NotifyPropertyChanged("Year");
}
}
private void NotifyPropertyChanged(string name)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
Unfortunately, this won't be enough. The List class does not support notifications from objects within its collection. Fortunately, there is an object that does - the BindingList. For the most part, the BindingList is used exactly like a List.
BindingList<Car> cars = new BindingList<Car>();
cars.Add(new Car("Ford", "Mustang", 1967));
cars.Add(new Car("Shelby AC", "Cobra", 1965));
cars.Add(new Car("Chevrolet", "Corvette Sting Ray", 1965));
_dgCars.DataSource = cars;
Now, if any external process, like a network thread, makes a change to a Car object, the DataGridView will automatically update to reflect the change.
Now we've got data in the DataGridView and any changes to the UI or the List will automatically update the other. Usually my properties aren't named something that are so user friendly. What happens when I want my columns named something else? This can be easily accomplished by disabling the AutoGenerateColumns property and by setting up the columns ourselves.
_dgCars.AutoGenerateColumns = false;
DataGridViewTextBoxColumn makeColumn = new DataGridViewTextBoxColumn();
makeColumn.DataPropertyName = "Make";
makeColumn.HeaderText = "The Car's Make";
DataGridViewTextBoxColumn modelColumn = new DataGridViewTextBoxColumn();
modelColumn.DataPropertyName = "Model";
modelColumn.HeaderText = "The Car's Model";
DataGridViewTextBoxColumn yearColumn = new DataGridViewTextBoxColumn();
yearColumn.DataPropertyName = "Year";
yearColumn.HeaderText = "The Car's Year";
_dgCars.Columns.Add(makeColumn);
_dgCars.Columns.Add(modelColumn);
_dgCars.Columns.Add(yearColumn);
BindingList<Car> cars = new BindingList<Car>();
cars.Add(new Car("Ford", "Mustang", 1967));
cars.Add(new Car("Shelby AC", "Cobra", 1965));
cars.Add(new Car("Chevrolet", "Corvette Sting Ray", 1965));
_dgCars.DataSource = cars;
Setting up the columns is pretty straight forward. There's all types of DataGridViewColumns, but I went with the basic TextBox version. All you have to do it set the HeaderText, which is what the user will see, and the DataPropertyName, which is the name of the property of the object that is bound to the DataGridView. Here's what our DataGridView looks like now:

I think that does it for binding a collection to a DataGridView. Data binding is a very powerful tool and we haven't even begun scratching the surface.
Look forward to reading more about WinForm and binding, 'beyond surface'.
Thanks
Thanks! That was very clear and helpfull!
I'll second that! This cleared things up that I hadn't gotten from any other tutorial.
Thanks for the info. Any way to enable the inserting of data?
You need to set the property AllowUserToAddRows to true. Any items added to the DataGridView will also be added to the collection bound to it (if you use a collection that supports two-way binding).
Hello, what if I've bound a list to the DataGridView in a multi-threaded application. How do I Invoke() in the automatic update of DataGridView in case of adding a new member to the list?
@Sindik That is not something I've found a clean solution to yet. At this point, I usually expose a control that can be used for the invoke. Either the actual DataGridView or the application's main form. Then, you'll want to invoke a function that actually adds to the list using the exposed control. That way, the automatic update is also done in the invoked code.
Try getting the calculated data on a BackgroundWorker, then updating the datasource on the RunWorkerCompleted event. This worked well for me.
I have created DataGridView and bind it with DataSource.
When I edit a single cell Value, and alos remain in that row, the dataset didn't get Changes.
Hi
Supose we have another class called Driver with Name and Age properties. Each car has only 1 driver and the class Car has a Driver property.
How to bind a column to the
Car.Driver.Name property ??
Thanks
The way I've handled this is to create a view that exposes the nested properties at the level of the view so that they show up in the datagridview. Here's an example:
Sorry, in the example above, change "Fault" in
to "Car" like
[language]
public class CarView { Car _Car;
public CarView() { }
public CarView(Car car) : this() { this._Car = car; }
public Car Car { get { return _Car; } }
public string DriverName { get { return _Car.Driver.Name; } }
public string Make { get { return _Car.Make; } } }
public static class CarExtension { public static CarView ToView(this Fault source) { return new CarView(source); } } [/language]
Exactly what I need, thanks a lot !
Thanks. Just what I was after!
Thanks! very helpfull for beginners like myself
How do you select what properties are displayed. In your example all the properties of the "car" were displayed. what if you only wanted model and year for example?
In my example code, I'm creating a column for each property and assigning it the name of the property I want displayed.
I make a column for each property, but you don't have to. Just don't add a column for the properties you don't want to see.
To hide a property just set [Browsable(false)] attribute right over the property
Where (in what class file) do you put the List?
It can be anywhere. You could make it a member field, or you could just create it in the constructor (like I did here). I like the member field so you can still access the data after the constructor ends.
The constructor of the Form class?
For my example application, yes.
Its very great example...great explanation...
Can you comment on the use of BindingSource to bind the List to the Grid? Something like this:
BindingSource1.DataSource = List; DataGridView1.DataSource = BindingSource1;
Hi
Thanks for the simple demo. Tried it on a simple new project and it works a treat.
On my existing app however, the datagridview is empty! Any ideas?
Rusty
Hi
Ignore me. I'm such a numpty! I was trying to bind to a LinkedList. Have changed and is now working fine.
Rusty
Thank you. This post answered all of the questions I had about updating a dataset. Very useful.
Thank you very much, great tutorial!
Has anyone tried a case where the datagrid is bound to a list object as a datasource. However, one of the object's attribute is a list of items, which will vary based on the value of another attribute. In the example above, say, based on the "Car's Make" selected, the "Car's Model" list should be automatically filtered, to show only the Car Models that are applicable for that Make.
You can autogenerate the columns and rows and still change the name of the columns by using the "DisplayName" attributes
I didn't know that. Thanks for the tip.
Hi is there a way to link it to an xml file?
private void tabStyle_Enter(object sender, EventArgs e) { XmlDataDocument myXml = new XmlDataDocument(); myXml.DataSet.ReadXml(Application.StartupPath + "\\dataGrid.xml"); dataGridView1.DataSource = myXml.DataSet; dataGridView1.DataMember = "Element"; }
"Element" is the XML element from which to populate the grid. In this example, while this is set to load when a tab is entered, it may be implemented by a button click event.
Repeated with the tags:
"Element" is the XML element from which to populate the grid. In this example, while this is set to load when a tab is entered, it may be implemented by a button click event.
Thanks for the tutorial. Helped me a lot. I am getting some data from the internet and want to show a part of the data in the DataGrid. I have the BindingList and the class. But is it possible that when I add columns, I just add 2 columns while I have 5 properties in the class?
Thanks again.
Yes. Just create columns for only the properties you want to display. Just make sure AutoGenerateColumns is set to false. Any other properties will simply be ignored by the binding engine.
A very useful example!
I just have one question :o) When i bind the list to the DataGridView the row for inserting new values disappears. It's possible to display it?
Thanks! ;)
how will i add items in the column using a textbox.
Thanks! It was easy to understand!
Dude, you really know how to write a clear tutorial. Thanks a million.
What makes this a great tutorial is, you start with the simplest most intuitive solution an ordinary person would think of, show how that doesn't quite work, and introduce the next level of complexity. Then show what doesn't quite work with that, and the next more complex solution, and so on.
Infinitely better than the kind of tutorial that says, "You have this object and that object and this other object, and you hook them all together like this...". The reader never has any idea why all those objects exist.
But I have a problem. I have to display the object as columns, and the propieties as rows. Is some way to do it keeping the binding? I'd love you till the end of time if you could answer this!
It worked! Great! Thanks!
Hi!
I've concatenated your tutorials' examples about serialization and this one to make datagrid viewable class that can be serialized. But there's a problem. I don't know how to perform it mostly because of
field. And there's one more question. When DataGrid is edited, we have our BindingList updated, right? But can I add some other functions that are need to be performed when something's changed in BindingList? Thank you very much in advance.
Great article, exactly what I was looking for. Thanks!
Thank you, great tutorial! Exactly what I need.
hi m facing a problem i have a datagrid whose data source is the databse in sql server and it retrieves one column ..i want to add one more column named rating to that same datagrid view named rating...
although i was successful doing that using the columns collection property of the data grid view but how can i add allow user to enter/add values in that newly created column rating and how can i add it to my database there in sql server...
please help...
regards,
vartika
Looks great, the only issue I have with the binding list is that it doesn't support a sort method. The examples I've seen to implement/create a sort method manually are very convoluted/confusing.
Fantastic Article!!! Exactly what I seeking! Thanks for sharing your talent!
Thanks - this is a great tutorial.
In my gridview, one of the columns is a combo box instead of strings or integers. I haven't been able to use this binding method to bind my collection to the gridview. I have tried implementing the property that represents the combo box as both enum and string but it doesn't work - the runtime doesn't like it.
Has anyone else got it to work where one of the columns in the gridview is a combo box?
Thanks in advance.
I'm having the same problem where I populate the grid from an XML file but am unable to have combobox options. Does anyone know how?
my application crashed all the when I move to another row of datagridview.
Scenario:
BindingList bindList = new BindingList();
DataGridView dgv = new DataGridView()
dgv.DataSource = bindList;
So, the dgv is populated with rows found in the bindList. is this correct?
Allow user to add rows is "TRUE" in dgv.
Step to reproduce the error: 1. move to blank row at the bottom. do nothing 2. select any row with records. or press ESC key Result: my Application will crash.
Why is this happening? Any help will be most apprecaited.
Hi guys. I have the same concern in DataBindings. when i add new object in my list the datasource doesnt add row. I think the problem is when I use DataBindings during form load it only binds list for editing purposes only, but not for adding... Is there any way to add object in my list and enforces the datasource to change and add my object in datasource without using: dataGridView.DataSource = Nothing dataGridView.DataSource = myList
That's Impractical.. Impractical when you have millions of List to be loaded...
Is it possible to bind, and change in database through a datagridview, joined tables? For example, table A has a foreign key to ID column of table B. But, while showing table A in DataGridView, I want to show B.Name, associated with that ID instead just that number which is useless to the user. That column would be read only, but I want to be able to change the rest of the DataGridView and update the changes to the database. Is it possible to do with adapters, command builder etc..?
This is an excellent tutorial that solved many of my problems. Great thanks for it. But I am thinking the solution for "How to notify when any car class object's property changed, without registering the event handler for every car object as I've done in the following example:
This can not be done for every object in list. Do you have any idea to tacle this?
You could add another event that's static. That way you only had to hook it once and it would be raised for all Car instances.
So, how do I support adding a row? Raise an event to rebind to a rebuilt BindingList?
That would work but may be slow, especially if there are thousands of rows. I would recommend switching to an ObservableCollection. This collection will raise an event that the DataGridView automatically catches to know when to update the display.
hi , excellent tutorial however can you let me know how can I display combobox say for a list of enums that are within a class, modifying the properties to return an array doesnot work
Hello,
How to implement adding and deleting rows with this method?
Cheers
The example and everyone's comments are all very good, found the solution to my issue. Thanks everyone!
Hello, very good and simple coding.
Thanks!
any chance to add a new row by users in this way?
Please, I have a problem that has disturbed me for days now. A bounded datagridview cannot have rows added to it. However, if the datasource has only few rows, the datagridview will only occupy a small portion (equal to the number of rows in the grid) of the form. How can I add rows to mask this gap? Please help me.
Hi your article is great. But i am having a problem. when i update a row in the gridview i can get back the object. however, when i add a new row i can't. the return value is null. Please help! thank you.
This is very handy and has helped me get started. However, I'm VC Studio is generating lots of code for me and CHANGING it where I don't want it to be changed. Where do I assign the grid's data source? I'm doing it in the initialize component function. Then, when I try to make one of the columns a drop down box everything starts going wacky. VC Studio takes out the data source assignment and when I compile I get tons of erros saying "Code generation for DataSource property failed; COptionClass (my class) is not marked as serializable when it clearly is. How do I properly assign the data source and, once that's done, how can I customize the rows?
Awesome tutorial. Easy to understands, and it worked (VS 2008).
Thanks!!!
simple and very impressive
What if one of the properties in your car class was an array? Is there a way to assign each element in that array to a column in the DataGridView?
Thanks!
Thanks Please continue...
Hi,
I got my project to link properly; however if I want some of the fields in the GridView to show up in a combobox, yet I only store a "Key" in my data how can I get it to show and be linked properly?
i.e.
I have on of the fields in cars is Brand yet I only store an ID such as 14689. However, I want this to be linked to the comboBox which lists 50 different brands in plainText, how do I get the ID to be linked to the text? and how do I get the ID to change if the selection in the comboBox changes?
This is the best databinding article I have read yet. Very clear, to the point, and RELEVANT example. Awesome job. Thank you!
Awesome job. Exactly what I was looking for.
Hi! This is very useful information in making Class and use in DataGrid as well. I want to know how can we save Car data in DataGrid and show from data base in DataGrid??? Kindly explain I am very confuse in doing so....
Many many thanks. Teaching a concept is an art. Most people use teaching to showcase their technical superiority. You just explained it simply and effectively.
A job very well done and once again, many thanks.
it is posible to bind cell properties? like if in my car class i have a Color propertie, and i whant that propertie to be used as the BackGroundColor of the row to wich it´s binded, is something like that posible?
i regularly forget how this works - and regularly come back to this page (in favourites) to re read.
Brilliant!
sahweet!! Thanks for posting this tutorial - exactly what I was looking for.
A complete C# datagridview tutorial
http://csharp.net-informations.com/datagridview/csharp-datagridview-tutorial.htm
an.
Great! Just what I wanted. Thanks
hi how would i bind a queue collection to a gridview
This is a great tutorial. This way of doing it really cleans things up.
But what am I missing? There is no support for sorting when you click the header cell on the DataGridView Control. The Rows do not sort?
While finding data r fill in data gridview. After that i add one more i want save it.becasue its an primarky for that table? How give modify for that? Please give some solution for that.
Hi I managed to bind my datagridview to a bindinglist, but how can I allow changes to be made from the datagridview? As of the moment my datagridview is like display only, I can change values internally but not from the datagridview.
Hi, I am agree with the others. This is a nice tutorial. But I didn't find exactly what I was looking for. I am trying to change the color of a DataGridViewCell in according to the value I get from the property of an object(I bind the datagrid with datasource). I don't know if my explanation is clear so I try with an example.
If I have an object like this(I hope that it has no errors I wrote it in speed) and I bind a datagrid like this:
I have what I want but I would like to color the cells for example color column1 in green if its value is "Exists" or _value1 is true otherwise in red. Is this possible to do without using
but maybe in the property get with a property like Browsable?
If someone can help. Thanks in advance =)
That was an excellent, to the point tutorial. Many thanks and great job.
I have troubles with a thread, because when one thread(diferent to the UI) try to add some object to the list, the complier say: You can´t do this from another thread, any idea?
Use delegates, like this:
Hello, I am having the following problem: I have a multitabbed form with 2-6 datagrids in each tabpage. When a new project is created I show this form so that the user adds rows if they do not exist or changes existing rows. For that purpose I fill the datasources of the datagrids with data coming from database. When a datasource is empty, because the user has not entered yet any data there, the datagridview shows only the headers, and I'd like it to show an empty new row so that the user can introduce data. In some grids this is working properly, and their datasource is also empty, but in some others it does not. Do you have an explanation? both bindingsources and datagrids have AllowNew, Allow to add rows property to true
Thanks in advance Natalia
The Reddest,
Much thanks for your article. It works great.
I have a question. Even though i don't implemnt the interface INotifyPropertyChanged, the grid-objects collection works as well.
When i update object, add object into the collection, the grid refreshed successfully.
BindingList improved in new version? Could you please advise.
INotifyPropertyChanged is only needed if you want changes to those properties to update the grid cell after they've been added. If all you're doing is adding and removing rows, then it's not needed. If, in your example, the property 'X' was changed after it was added to the DataGrid, the UI would not update with the new value.
Thanks A lot this is a very useful and interested article thank
This article is in a very - cs-Style: Clever and Strict. It all ready helped me - with my small new Project. http://www.dapfor.com/en/net-suite/net-grid/features/headers-and-columns
Excellent !! Thank you Man ;)
how copy selected row of datagridview to other datagridview in c#?
Its very usefull article . Great..........
you are forgetting an important line of code, the call to DataBind()
Awesome!! Thanks a lot for this post!! I have tried microsoft documentation, stackoverflow, etc... nothing helped me, but this. Thank you. ;]
Very clear, but i have a question: If the row is invalid (because the binded object is NonValid) how can force the user to NonClick other rows? I don't find a clear to do that, thanks.
Hi Brandon,
I used your code. I feel pretty much like every body as how clean and well explained each line of code is. So far I have some issues when updating. My access table is small. Three fields. id (primary key and autonumber), class (text), percent (numeric integer). Updating Class is not a problem. Updating Percent makes the whole thing crash as well as when I insert a new record. Error: "OleDbException was unhandled. Syntax error in UPDATE statement." Any ideas??? Thanks
Thank you very much this tutorial, it's better than msdn...! And I'd like to ask, what can I do if my data are in member strucure, for example:
How can I to view in datagridview, as: id | proj1.x | proj1,y | proj2.x | proj2.y ?
Thanks!
Solved!
public partial class MainForm : Form { internal List<point> points;