C# 是否可以将复杂类型的属性绑定到数据网格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/121274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to bind complex type properties to a datagrid?
提问by Xerx
How would I go about binding the following object, Car, to a gridview?
我将如何将以下对象 Car 绑定到 gridview?
public class Car { long Id {get; set;} Manufacturer Maker {get; set;} } public class Manufacturer { long Id {get; set;} String Name {get; set;} }
The primitive types get bound easy but I have found no way of displaying anything for Maker. I would like for it to display the Manufacturer.Name. Is it even possible?
原始类型很容易绑定,但我发现无法为 Maker 显示任何内容。我希望它显示制造商名称。甚至有可能吗?
What would be a way to do it? Would I have to store ManufacturerId in Car as well and then setup an lookupEditRepository with list of Manufacturers?
有什么办法可以做到?我是否还必须将 ManufacturerId 存储在 Car 中,然后设置一个包含制造商列表的 lookupEditRepository?
回答by hollystyles
public class Manufacturer
{
long Id {get; set;}
String Name {get; set;}
public override string ToString()
{
return Name;
}
}
Override the to string method.
覆盖 to string 方法。
回答by Ben Hoffstein
Yes, you can create a TypeDescriptionProvider to accomplish nested binding. Here is a detailed example from an MSDN blog:
是的,您可以创建一个 TypeDescriptionProvider 来完成嵌套绑定。这是来自 MSDN 博客的详细示例:
回答by Seb Nilsson
Just use a List and set the DataMemberto the string "Maker.Name" and if you want the DataKeyFieldto use car's ID just set that to "ID".
只需使用列表并将DataMember设置为字符串“Maker.Name”,如果您希望DataKeyField使用汽车的 ID,只需将其设置为“ID”。
dataGrid.DataSource = carList;
dataGrid.DataMember = "Maker.Name";
dataGrid.DataKeyField = "ID";
dataGrid.DataBind();
I know that works in the repeater-control, at least...
我知道这在中继器控制中有效,至少......
回答by ManiacZX
The way that I approached this in a recent application was to create my own DataGridViewColumn and DataGridViewCell classes inheriting off of one of the existing ones such as DataGridViewTextBoxColumn and DataGridViewTextBoxCell.
我在最近的一个应用程序中处理这个问题的方法是创建我自己的 DataGridViewColumn 和 DataGridViewCell 类,继承现有的类之一,例如 DataGridViewTextBoxColumn 和 DataGridViewTextBoxCell。
Depending on the type of cell you want, you could use others such as Button, Checkbox, ComboBox, etc. Just take a look at the types available in System.Windows.Forms.
根据所需的单元格类型,您可以使用其他单元格,例如按钮、复选框、组合框等。只需查看 System.Windows.Forms 中可用的类型即可。
The cells deal with their value's as objects so you will be able to pass your Car class into the cell's value.
单元格将它们的值作为对象处理,因此您可以将 Car 类传递到单元格的值中。
Overriding SetValue and GetValue will allow you to have any additional logic you need to handle the value.
覆盖 SetValue 和 GetValue 将允许您拥有处理该值所需的任何其他逻辑。
For example:
例如:
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 "";
}
}
}
On the column class the main thing you need to do is set the CellTemplate to your custom cell class.
在列类上,您需要做的主要事情是将 CellTemplate 设置为您的自定义单元格类。
public class CarColumn : System.Windows.Forms.DataGridViewTextBoxColumn
{
public CarColumn(): base()
{
CarCell c = new CarCell();
base.CellTemplate = c;
}
}
By using these custom Column/Cells on the DataGridView it allows you to add a lot of extra functionality to your DataGridView.
通过在 DataGridView 上使用这些自定义列/单元格,它允许您向 DataGridView 添加许多额外的功能。
I used them to alter the displayed formatting by overriding GetFormattedValue to apply custom formatting to the string values.
我使用它们通过覆盖 GetFormattedValue 将自定义格式应用于字符串值来更改显示的格式。
I also did an override on Paint so that I could do custom cell highlighting depending on value conditions, altering the cells Style.BackColor to what I wanted based on the value.
我还对 Paint 进行了覆盖,以便我可以根据值条件进行自定义单元格突出显示,根据值将单元格 Style.BackColor 更改为我想要的。
回答by Seth Petry-Johnson
If you want to expose specific, nested properties as binding targets, then Ben Hoffstein's answer (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) is pretty good. The referenced article is a bit obtuse, but it works.
如果您想公开特定的嵌套属性作为绑定目标,那么 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)非常好。引用的文章有点晦涩,但确实有效。
If you just want to bind a column to a complex property (e.g. Manufacturer) and override the rendering logic, then either do what ManiacXZ recommended, or just subclass BoundField and provide a custom implementation of FormatDataValue(). This is similar to overriding ToString(); you get an object reference, and you return the string you want displayed in your grid.
如果您只想将列绑定到复杂属性(例如制造商)并覆盖呈现逻辑,那么要么执行 ManiacXZ 推荐的操作,要么只是继承 BoundField 并提供 FormatDataValue() 的自定义实现。这类似于覆盖 ToString(); 你得到一个对象引用,然后返回你想在你的网格中显示的字符串。
Something like this:
像这样的东西:
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);
}
}
}
Just add a ManufacturerField to your grid, specifying "Manufacturer" as the data field, and you're good to go.
只需在您的网格中添加一个 ManufacturerField,指定“Manufacturer”作为数据字段,您就可以开始使用了。
回答by Ryan Spears
I would assume you could do the following:
我假设您可以执行以下操作:
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;}
}
回答by n8wrl
Here's another option I got working:
这是我工作的另一个选择:
<asp:TemplateColumn
HeaderText="Maker">
<ItemTemplate>
<%#Eval("Maker.Name")%>
</ItemTemplate>
</asp:TemplateColumn>
Might be ASP.NET 4.0 specific but it works like a charm!
可能是 ASP.NET 4.0 特定的,但它的作用就像一个魅力!
回答by karlipoppins
Allright guys... This question was posted waaay back but I just found a fairly nice & simple way to do this by using reflection in the cell_formatting event to go retrieve the nested properties.
好吧,伙计们...这个问题已经发布回来了,但我刚刚找到了一种相当不错且简单的方法,通过在 cell_formatting 事件中使用反射来检索嵌套属性。
Goes like this:
是这样的:
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;
}
}
And that's it! You can now use the familiar syntax "ParentProp.ChildProp.GrandChildProp" in the DataPropertyName for your column.
就是这样!您现在可以在列的 DataPropertyName 中使用熟悉的语法“ParentProp.ChildProp.GrandChildProp”。