我如何将以下对象Car加载到gridview?
public class Car { long Id {get; set;} Manufacturer Maker {get; set;} } public class Manufacturer { long Id {get; set;} String Name {get; set;} }
原始类型很容易绑定,但我发现无法为Maker显示任何内容。我想让它显示Manufacturer.Name。它甚至可能吗?
有什么方法可以做到这一点?我是否还必须将ManufacturerId存储在Car中,然后使用制造商列表设置lookupEditRepository?
答案 0 :(得分:26)
好吧伙计......这个问题已经发布了回来,但我发现了一个相当不错的&通过在cell_formatting事件中使用反射来检索嵌套属性的简单方法。
这样:
private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridView grid = (DataGridView)sender;
DataGridViewRow row = grid.Rows[e.RowIndex];
DataGridViewColumn col = grid.Columns[e.ColumnIndex];
if (row.DataBoundItem != null && col.DataPropertyName.Contains("."))
{
string[] props = col.DataPropertyName.Split('.');
PropertyInfo propInfo = row.DataBoundItem.GetType().GetProperty(props[0]);
object val = propInfo.GetValue(row.DataBoundItem, null);
for (int i = 1; i < props.Length; i++)
{
propInfo = val.GetType().GetProperty(props[i]);
val = propInfo.GetValue(val, null);
}
e.Value = val;
}
}
就是这样!您现在可以在列的DataPropertyName中使用熟悉的语法“ParentProp.ChildProp.GrandChildProp”。
答案 1 :(得分:12)
是的,您可以创建TypeDescriptionProvider来完成嵌套绑定。以下是MSDN博客的详细示例:
答案 2 :(得分:7)
我在最近的一个应用程序中解决这个问题的方法是创建我自己的DataGridViewColumn和DataGridViewCell类继承一个现有的类,如DataGridViewTextBoxColumn和DataGridViewTextBoxCell。
根据所需的单元格类型,您可以使用其他类型,如Button,Checkbox,ComboBox等。只需查看System.Windows.Forms中可用的类型。
单元格将它们的值作为对象处理,这样您就可以将Car类传递给单元格的值。
重写SetValue和GetValue将允许您拥有处理该值所需的任何其他逻辑。
例如:
public class CarCell : System.Windows.Forms.DataGridViewTextBoxCell
{
protected override object GetValue(int rowIndex)
{
Car car = base.GetValue(rowIndex) as Car;
if (car != null)
{
return car.Maker.Name;
}
else
{
return "";
}
}
}
在列类中,您需要做的主要事情是将CellTemplate设置为自定义单元类。
public class CarColumn : System.Windows.Forms.DataGridViewTextBoxColumn
{
public CarColumn(): base()
{
CarCell c = new CarCell();
base.CellTemplate = c;
}
}
通过在DataGridView上使用这些自定义Column / Cells,它允许您向DataGridView添加许多额外功能。
我使用它们来改变显示的格式,重写GetFormattedValue以将自定义格式应用于字符串值。
我还对Paint进行了覆盖,以便我可以根据值条件进行自定义单元格高亮显示,根据值将单元格Style.BackColor更改为我想要的值。
答案 3 :(得分:5)
public class Manufacturer
{
long Id {get; set;}
String Name {get; set;}
public override string ToString()
{
return Name;
}
}
覆盖to string方法。
答案 4 :(得分:2)
只需使用列表并将 DataMember 设置为字符串“Maker.Name”,如果您希望 DataKeyField 使用汽车的ID,只需将其设置为“ID”
dataGrid.DataSource = carList;
dataGrid.DataMember = "Maker.Name";
dataGrid.DataKeyField = "ID";
dataGrid.DataBind();
我知道这对转发器控制起作用,至少......
答案 5 :(得分:2)
如果要将特定的嵌套属性公开为绑定目标,那么Ben Hoffstein的答案(http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx)非常好。引用的文章有点迟钝,但它确实有用。
如果您只想将列绑定到复杂属性(例如制造商)并覆盖渲染逻辑,那么要么执行ManiacXZ推荐的操作,要么只创建BoundField的子类并提供FormatDataValue()的自定义实现。这类似于重写ToString();你得到一个对象引用,然后返回你想要在网格中显示的字符串。
这样的事情:
public class ManufacturerField : BoundField
{
protected override string FormatDataValue(object dataValue, bool encode)
{
var mfr = dataValue as Manufacturer;
if (mfr != null)
{
return mfr.Name + " (ID " + mfr.Id + ")";
}
else
{
return base.FormatDataValue(dataValue, encode);
}
}
}
只需将一个ManufacturerField添加到您的网格中,指定“制造商”作为数据字段,您就可以了。
答案 6 :(得分:2)
这是我工作的另一个选择:
<asp:TemplateColumn
HeaderText="Maker">
<ItemTemplate>
<%#Eval("Maker.Name")%>
</ItemTemplate>
</asp:TemplateColumn>
可能是ASP.NET 4.0特定的,但它就像一个魅力!
答案 7 :(得分:1)
我认为你可以做到以下几点:
public class Car
{
public long Id {get; set;}
public Manufacturer Maker {private get; set;}
public string ManufacturerName
{
get { return Maker != null ? Maker.Name : ""; }
}
}
public class Manufacturer
{
long Id {get; set;}
String Name {get; set;}
}