DataGridView - Use DataPropertyName to show child element property

Just do this:

Mask the property you want to get a childvalue from with [Browsable(false)] so it wont show up in the datagrid. Then create a NEW property in your class that holds the child object which has only a "get" method showing the childproperty value: For example:

[Browsable(false)] //Because we use the CreatorUsernameProperty to do this.
public virtual User Creator { get; set; }

[DisplayName("Creator")] //shows like this in the grid
public string CreatorUsername => Creator?.Username;

If you need to be more generic (i.e. using DataPropertyName = "MyProp1.MyProp2.MyProp3") you can use this

private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    DataGridViewColumn column = Grid.Columns[e.ColumnIndex];
    if (column.DataPropertyName.Contains("."))
    {
        object data = Grid.Rows[e.RowIndex].DataBoundItem;
        string[] properties = column.DataPropertyName.Split('.');
        for (int i = 0; i < properties.Length && data != null; i++)
            data = data.GetType().GetProperty(properties[i]).GetValue(data);
        Grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = data;
    }
}

In case you want to use many child elements like this:

class MyClass
{
   public int Id;
   public MyOtherClass OtherClass;
}

class MyOtherClass
{
   public string Name;
   public int Number;
}

How about:

1st solution Set value for each cell in some event (mabye another one is better), manually, after setting datasource, for example:

private void dgv_CellFormatting( object sender, DataGridViewCellFormattingEventArgs e )
{
   MyClass data = dgv.Rows[ e.RowIndex ].DataBoundItem as MyClass;

   dgv.Rows[ e.RowIndex ].Cells[ "colName" ].Value = data.OtherClass.Name;
   dgv.Rows[ e.RowIndex ].Cells[ "colNumber" ].Value = data.OtherClass.Number;
}

2nd solution What about creating proper DataTable from the data and then just bind it?

I'd be thankful for any opinion ;-)


You can override ToString method in the entity child for example:

public class FormulariosENT {

    #region PROPERTIES

    public int IdFromulario { get; set; }
    public string DescripcionFormulario { get; set; }

    #endregion

    #region PUBLIC METHODS
    public override string ToString() {

        return DescripcionFormulario;
    }

And later bind the entity child name.