绑定对象DataGridView C#

我有一个DataGridView和一个我想要显示的对象列表。

对象是这些:

public class Entity { public int ID { get; set; } } public class Travel: Entity { public Service Service { get; set; } public City Source { get; set; } public City Destiny { get; set; } public decimal Price { get; set; } } public class Service: Entity { public string Name { get; set; } } public class City: Entity { public string Name { get; set; } // Max 50 chars } 

在我的表单中,我绑定旅行对象的列表,如下所示:

 List travels = logic.GetAllTravels(); DgvRecorridos.DataSource = travels; 

我得到以下内容:

在此处输入图像描述

我想获得服务名称,源城和命运之城。

提前致谢。

而不是执行以下代码:

 List travels = logic.GetAllTravels(); DgvRecorridos.DataSource = travels; 

做这个:

 List travels = logic.GetAllTravels(); BindingSource bs = new BindingSource(); bs.DataSource = travels; DgvRecorridos.AutoGenerateColumn = false; DgvRecorridos.DataSource = bs; 

然后,手动添加列:

 DataGridViewColumn col1 = new DataGridViewTextBoxColumn(); col1.DataPropertyName = "Service.Name"; col1.HeaderText = "Service Name"; dataGridView1.Columns.Add(col1); DataGridViewColumn col2 = new DataGridViewTextBoxColumn(); col2.DataPropertyName = "City.Name"; col2.HeaderText = "City Name"; dataGridView1.Columns.Add(col2); DataGridViewColumn col3 = new DataGridViewTextBoxColumn(); col3.DataPropertyName = "City.Name"; col3.HeaderText = "Destiny Name"; dataGridView1.Columns.Add(col3); DataGridViewColumn col4 = new DataGridViewTextBoxColumn(); col4.DataPropertyName = "Price"; col4.HeaderText = "Price"; dataGridView1.Columns.Add(col4); 

然后,为DataGridView添加一个单元格格式化事件处理程序:

 private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dataGridView1.Rows[e.RowIndex].DataBoundItem != null && dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains(".")) { e.Value = BindProperty(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName); } } private string BindProperty(object property, string propertyName) { string retValue = ""; if (propertyName.Contains(".")) { PropertyInfo[] arrayProperties; string leftPropertyName; leftPropertyName = propertyName.Substring(0, propertyName.IndexOf(".")); arrayProperties = property.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in arrayProperties) { if (propertyInfo.Name == leftPropertyName) { retValue = BindProperty(propertyInfo.GetValue(property, null), propertyName.Substring(propertyName.IndexOf(".") + 1)); break; } } } else { Type propertyType; PropertyInfo propertyInfo; propertyType = property.GetType(); propertyInfo = propertyType.GetProperty(propertyName); retValue = propertyInfo.GetValue(property, null).ToString(); } return retValue; } 

有关单元格格式的完整指南,请浏览Antonio Bello的博客,这是我的想法。 ^ _ ^我两天前在这里问了同样的问题,得到了和你一样的答案,我知道这不是你想要做的。 希望它能帮到你。

 List travels = logic.GetAllTravels(); var _bind = from a in travels select new { Servicename = a.Service.Name, SourceName = a.Source.Name, DestinyName = a.Destiny.Name, Price = a.Price }; DgvRecorridos.DataSource = _bind; 

要么

 List travels = logic.GetAllTravels(); var _bind = travels.Select(a => new { Servicename = a.Service.Name, SourceName = a.Source.Name, DestinyName = a.Destiny.Name, Price = a.Price }); DgvRecorridos.DataSource = _bind; 

你的设计很奇怪。 我有另一种方法是覆盖你的类(服务和城市)的ToString()方法,如下所示:

 public class Service: Entity { public string Name { get; set; } public override string ToString(){ return Name; } } public class City: Entity { public string Name { get; set; } // Max 50 chars public override string ToString(){ return Name; } } 

这很好用。 再次,你的设计有点奇怪^ _ ^

CellFormatting和BindProperty方法中的所有代码似乎都过多了。 我的意思是,基本上必须做的事情,但我认为它已经完成了。 我在要绑定到网格行的对象中实现了INotifyPropertyChanged,并将这些对象放入BindingList中。 BindingList直接用作网格的数据源。

这种方法意味着在您将映射到网格行的基本实体类中输入更多内容,但我认为它在其他地方节省了更多。 要在您的类中实现INotifyPropertyChanged:

 public class Entity: INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public Entity() { Selected = false; } private bool _selected; public bool Selected { get { return _selected; } set { if (_selected != value) { _selected = value; OnPropertyChanged(nameof(Selected)); } } } protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } 

然后在网格中放置一个列,并为其指定DataPropertyName“Selected”,以匹配应该出现在该列中的Entity中的属性名称。 显然,将您想要的任何属性添加到网格中,匹配实体的属性。 关键是要确保通过调用PropertyChanged来实现属性设置器。

这将使您在网格和对象列表之间进行双向绑定。

我的个人意见:即使这样的代码太多了。 我发现自己经常写这些显而易见的事情:按名称获取属性并将其映射到知道该名称的其他内容(如本例中的网格列)。 我无法理解为什么这些东西不会自动连接起来。 列表和网格应该有足够的意义来自己计算这个基本安排。 零行代码。 好的,一行代码。 Grid.Datasource = List。 所以我就是这样做的。 我想知道更少的代码方式来做到这一点。