[英]Binding objects 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<Travel> travels = logic.GetAllTravels();
DgvRecorridos.DataSource = travels;
我得到以下内容:
我想获得服务的名称,来源城市和命运城市。
提前致谢。
List<Travel> 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<Travel> 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;
而不是执行以下代码:
List<Travel> travels = logic.GetAllTravels();
DgvRecorridos.DataSource = travels;
做这个:
List<Travel> 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的博客上浏览此处 ,这是我的主意。 ^ _ ^两天前我在这里也问过同样的问题,并且得到了与您相同的答案,我知道这也不是您想要做的。 希望对您有帮助。
您的设计是如此奇怪。 我还有另一种方法是像这样重写您的类(服务和城市)的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以匹配应出现在该列中的Entity中的属性名称。 显然,将所需的任何属性添加到网格中,以匹配实体的属性。 关键是要确保通过调用PropertyChanged来实现属性设置器。
这使您可以在网格和对象列表之间进行双向绑定。
我个人的看法:即使这样也太多了。 我发现自己一直在写这些显而易见的事情:通过名称获取属性并将其映射到知道该名称的其他对象(例如本示例中的grid列)。 这些事情并不仅会自动引起人们的兴趣,这超出了我的理解。 列表和网格应具有足够的意识来自行确定此基本安排。 零行代码。 好的,一行代码。 Grid.Datasource =列表。 所以这就是我的方法。 我很想知道更少的代码行来做到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.