Is it possible to bind complex type properties to a datagrid?

Solution 1:

Allright guys... This question was posted waaay back but I just found a fairly nice & simple way to do this by using reflection in the cell_formatting event to go retrieve the nested properties.

Goes like this:

    private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {

        DataGridView grid = (DataGridView)sender;
        DataGridViewRow row = grid.Rows[e.RowIndex];
        DataGridViewColumn col = grid.Columns[e.ColumnIndex];
        if (row.DataBoundItem != null && col.DataPropertyName.Contains("."))
        {
            string[] props = col.DataPropertyName.Split('.');
            PropertyInfo propInfo = row.DataBoundItem.GetType().GetProperty(props[0]);
            object val = propInfo.GetValue(row.DataBoundItem, null);
            for (int i = 1; i < props.Length; i++)
            {
                propInfo = val.GetType().GetProperty(props[i]);
                val = propInfo.GetValue(val, null);
            }
            e.Value = val;
        }
    }

And that's it! You can now use the familiar syntax "ParentProp.ChildProp.GrandChildProp" in the DataPropertyName for your column.

Solution 2:

Yes, you can create a TypeDescriptionProvider to accomplish nested binding. Here is a detailed example from an MSDN blog:

http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx

Solution 3:

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.

Solution 4:

    public class Manufacturer
    {
       long Id {get; set;}
       String Name {get; set;}

       public override string ToString()
       {
          return Name;
       }
    }

Override the to string method.