是否可以将复杂类型属性绑定到数据网格?
我如何将以下对象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,然后使用制造商列表设置lookupEditRepository?
解决方案
public class Manufacturer { long Id {get; set;} String Name {get; set;} public override string ToString() { return Name; } }
覆盖to字符串方法。
是的,我们可以创建TypeDescriptionProvider来完成嵌套绑定。这是MSDN博客中的详细示例:
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
只需使用一个List并将DataMember设置为字符串" Maker.Name",如果我们希望DataKeyField使用汽车的ID,只需将其设置为" ID"即可。
dataGrid.DataSource = carList; dataGrid.DataMember = "Maker.Name"; dataGrid.DataKeyField = "ID"; dataGrid.DataBind();
我知道至少在中继器控制中可以使用。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我在最近的应用程序中解决此问题的方法是创建自己的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上使用这些自定义列/单元格,它使我们可以向DataGridView添加很多额外的功能。
我使用它们通过覆盖GetFormattedValue来将自定义格式应用于字符串值来更改显示的格式。
我还对Paint进行了覆盖,以便可以根据值条件进行自定义单元格突出显示,从而根据值将单元格Style.BackColor更改为所需的值。
如果我们想将特定的嵌套属性作为绑定目标公开,则本霍夫斯坦(Ben Hoffstein)的答案(http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-到数据源的第二级属性.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添加到网格中,将" Manufacturer"指定为数据字段,就可以了。
我认为我们可以执行以下操作:
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;} }