DataGridView - использование DataPropertyName для отображения свойства дочернего элемента
Позволяет изобразить, что у меня есть следующие классы
public class Master
{
public string MasterName = "Something";
public List<Detail> details = new List<Detail>();
}
public class Detail
{
public string Foo = "Test";
}
И затем я хочу показать коллекцию объектов Details в DataGridView, используя код ниже
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "Details.Foo";
column.HeaderText = "Foo header";
dgv.Columns.Add(column);
Столбец отображается в сетке, но без значения
Ответы
Ответ 1
Вы можете переопределить метод ToString в дочернем объекте, например:
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;
}
И позже свяжите дочернее имя объекта.
Ответ 2
Если вам нужно быть более общим (т.е. используя DataPropertyName = "MyProp1.MyProp2.MyProp3"
), вы можете использовать этот
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;
}
}
Ответ 3
Если вы хотите использовать много дочерних элементов, например:
class MyClass
{
public int Id;
public MyOtherClass OtherClass;
}
class MyOtherClass
{
public string Name;
public int Number;
}
Как насчет:
1-е решение
Задайте значение для каждой ячейки в каком-либо событии (например, лучше другое), вручную, после установки источника данных, например:
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;
}
2-е решение
Как насчет создания надлежащего DataTable из данных, а затем просто привязать его?
Я был бы благодарен за любое мнение; -)
Ответ 4
Просто сделайте следующее:
Маскируйте свойство, из которого вы хотите получить дочернее значение, с помощью [Browsable (false)], чтобы он не отображался в datagrid.
Затем создайте новое свойство в своем классе, которое содержит дочерний объект, который имеет только метод "get", показывающий значение childproperty:
Например:
[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;
Ответ 5
где ваш файл? вы должны привести к источнику. что он найдет его.
вы можете сделать это
источник:
-
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; }
}
}
Ответ 6
Буби, ответ отличный. Я добавил небольшой твик, который позволяет подходу работать, если вы используете BindingListView.
Редактировать: этот подход отключает сортировку по столбцам, расположенным через подпроцесс. Не уверен, как это исправить на данный момент.
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;
}