The way that I approached this in a recent application was to create my own DataGridViewColumn and DataGridViewCell classes inheriting off of one of the existing ones such as DataGridViewTextBoxColumn and DataGridViewTextBoxCell.
Depending on the type of cell you want, you could use others such as Button, Checkbox, ComboBox, etc. Just take a look at the types available in System.Windows.Forms.
The cells deal with their value's as objects so you will be able to pass your Car class into the cell's value.
Overriding SetValue and GetValue will allow you to have any additional logic you need to handle the value.
For example:
public class CarCell : System.Windows.Forms.DataGridViewTextBoxCell
{
protected override object GetValue(int rowIndex)
{
Car car = base.GetValue(rowIndex) as Car;
if (car != null)
{
return car.Maker.Name;
}
else
{
return "";
}
}
}
On the column class the main thing you need to do is set the CellTemplate to your custom cell class.
public class CarColumn : System.Windows.Forms.DataGridViewTextBoxColumn
{
public CarColumn(): base()
{
CarCell c = new CarCell();
base.CellTemplate = c;
}
}
By using these custom Column/Cells on the DataGridView it allows you to add a lot of extra functionality to your DataGridView.
I used them to alter the displayed formatting by overriding GetFormattedValue to apply custom formatting to the string values.
I also did an override on Paint so that I could do custom cell highlighting depending on value conditions, altering the cells Style.BackColor to what I wanted based on the value.