DataGridView - using a DataPropertyName to display the property of a child

Lets depict that I have the following classes

public class Master { public string MasterName = "Something"; public List<Detail> details = new List<Detail>(); } public class Detail { public string Foo = "Test"; } 

And then I want to show a collection of Details objects in a DataGridView using the code below

 DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Details.Foo"; column.HeaderText = "Foo header"; dgv.Columns.Add(column); 

The column appears in the grid, but without a value

+10
source share
6 answers

You can override the ToString method in a child object, 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 child name of the object.

+2
source

If you need to be more general (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; } } 
+11
source

If you want to use many children, for example:

 class MyClass { public int Id; public MyOtherClass OtherClass; } class MyOtherClass { public string Name; public int Number; } 

What about:

1st solution Set a value for each cell in an event (for example, something else is better), manually, after setting the data source, 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 How about creating the proper DataTable from the data and then just bind it?

I would be grateful for any opinion; -)

+4
source

Just do the following:

Mask the property from which you want to get the child value with [Browsable (false)] so that it does not appear in the datagrid. Then create a new property in your class that contains a child object that has only the get method showing the value of childproperty: 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; 
+1
source

where is your file? you must lead to the source. that he will find him. You can do it

a source:

  •  List<Detail> list = new List<Detail>(); for (int i = 0; i < 10; i++) { Detail d = new Detail(); d.Foo = "test"; list.Add(d); } this.dgv.DataSource = list; this.dgv.Columns[0].Visible = false; DataGridViewTextBoxColumn dgvc = new DataGridViewTextBoxColumn(); dgvc.HeaderText = "列标题"; dgvc.DataPropertyName = "foo"; this.dgv.Columns.Add(dgvc); 
  •  public class Detail { private string foo; public string Foo { get { return foo; } set { foo = value; } } } 
0
source

Bubi, the answer is excellent. I added a little tweak that allows the approach to work if you use a BindingListView .

Edit: this approach disables sorting by columns located through the subprocess. Not sure how to fix it at the moment.

 if (column.DataPropertyName.Contains(".")) { object data = dgv.Rows[e.RowIndex].DataBoundItem; if (data is ICustomTypeDescriptor ictd) // support BindingListView data = ictd.GetPropertyOwner(null); string[] properties = column.DataPropertyName.Split('.'); for (int i = 0; i < properties.Length && data != null; i++) data = data.GetType().GetProperty(properties[i])?.GetValue(data); e.Value = data; } 
0
source

All Articles