本指南演示了在运行时刻如何创建分层级的主/从数据源,并与报表进行绑定。
要把报表绑定到自定义对象的集合,则执行下列操作。
为数据对象实现 ITypedList 接口
为了让 XtraReport 能使用由运行时刻所创建对象组成的主/从数据源正确工作,此数据源必须实现了 ITypedList 接口。 下面的代码演示了如何为三层的 Supplier-Product-OrderDetail 数据源实现 ITypedList 接口。
C# | 复制代码 |
---|---|
using System; using System.Collections; using System.ComponentModel; // ... public class SupplierCollection : ArrayList, ITypedList { PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { if (listAccessors != null && listAccessors.Length > 0) { PropertyDescriptor listAccessor = listAccessors[listAccessors.Length - 1]; if (listAccessor.PropertyType.Equals(typeof(ProductCollection))) return TypeDescriptor.GetProperties(typeof(Product)); else if (listAccessor.PropertyType.Equals(typeof(OrderDetailCollection))) return TypeDescriptor.GetProperties(typeof(OrderDetail)); } return TypeDescriptor.GetProperties(typeof(Supplier)); } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return "Suppliers"; } } public class Supplier { static int nextID = 0; int id; string name; ProductCollection products = new ProductCollection(); public ProductCollection Products { get { return products; } } public int SupplierID { get { return id; } } public string CompanyName { get { return name; } } public Supplier(string name) { this.name = name; this.id = nextID; nextID++; } public void Add(Product product) { products.Add(product); } } public class ProductCollection : ArrayList, ITypedList { PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return TypeDescriptor.GetProperties(typeof(Product)); } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return "Products"; } } public class Product { static int nextID = 0; OrderDetailCollection orderDetails = new OrderDetailCollection(); int suppID; int prodID; string name; public int SupplierID { get { return suppID; } } public int ProductID { get { return prodID; } } public string ProductName { get { return name; } } public OrderDetailCollection OrderDetails { get { return orderDetails; } } public Product(int suppID, string name) { this.suppID = suppID; this.name = name; this.prodID = nextID; nextID++; } } public class OrderDetailCollection : ArrayList, ITypedList { PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return TypeDescriptor.GetProperties(typeof(OrderDetail)); } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return "OrderDetails"; } } public class OrderDetail { int prodID; short quantity; public int ProductID { get { return prodID; } } public short Quantity { get { return quantity; } } public OrderDetail(int prodID, int quantity) { this.prodID = prodID; this.quantity = Convert.ToInt16(quantity); } } |
Visual Basic | 复制代码 |
---|---|
Imports System Imports System.Collections Imports System.ComponentModel ' ... Public Class SupplierCollection Inherits ArrayList Implements ITypedList Private Function GetItemProperties(ByVal listAccessors() As PropertyDescriptor) _ As PropertyDescriptorCollection Implements ITypedList.GetItemProperties If listAccessors IsNot Nothing AndAlso listAccessors.Length > 0 Then Dim listAccessor As PropertyDescriptor = listAccessors(listAccessors.Length - 1) If listAccessor.PropertyType.Equals(GetType(ProductCollection)) Then Return TypeDescriptor.GetProperties(GetType(Product)) ElseIf listAccessor.PropertyType.Equals(GetType(OrderDetailCollection)) Then Return TypeDescriptor.GetProperties(GetType(OrderDetail)) End If End If Return TypeDescriptor.GetProperties(GetType(Supplier)) End Function Private Function GetListName(ByVal listAccessors() As PropertyDescriptor) As String _ Implements ITypedList.GetListName Return "Suppliers" End Function End Class Public Class Supplier Private Shared nextID As Integer = 0 Private id As Integer Private name As String Private products_Renamed As New ProductCollection() Public ReadOnly Property Products() As ProductCollection Get Return products_Renamed End Get End Property Public ReadOnly Property SupplierID() As Integer Get Return id End Get End Property Public ReadOnly Property CompanyName() As String Get Return name End Get End Property Public Sub New(ByVal name As String) Me.name = name Me.id = nextID nextID += 1 End Sub Public Sub Add(ByVal product As Product) products_Renamed.Add(product) End Sub End Class Public Class ProductCollection Inherits ArrayList Implements ITypedList Private Function GetItemProperties(ByVal listAccessors() As PropertyDescriptor) As PropertyDescriptorCollection Implements ITypedList.GetItemProperties Return TypeDescriptor.GetProperties(GetType(Product)) End Function Private Function GetListName(ByVal listAccessors() As PropertyDescriptor) As String _ Implements ITypedList.GetListName Return "Products" End Function End Class Public Class Product Private Shared nextID As Integer = 0 Private orderDetails_Renamed As New OrderDetailCollection() Private suppID As Integer Private prodID As Integer Private name As String Public ReadOnly Property SupplierID() As Integer Get Return suppID End Get End Property Public ReadOnly Property ProductID() As Integer Get Return prodID End Get End Property Public ReadOnly Property ProductName() As String Get Return name End Get End Property Public ReadOnly Property OrderDetails() As OrderDetailCollection Get Return orderDetails_Renamed End Get End Property Public Sub New(ByVal suppID As Integer, ByVal name As String) Me.suppID = suppID Me.name = name Me.prodID = nextID nextID += 1 End Sub End Class Public Class OrderDetailCollection Inherits ArrayList Implements ITypedList Private Function GetItemProperties(ByVal listAccessors() As PropertyDescriptor) As PropertyDescriptorCollection Implements ITypedList.GetItemProperties Return TypeDescriptor.GetProperties(GetType(OrderDetail)) End Function Private Function GetListName(ByVal listAccessors() As PropertyDescriptor) As String _ Implements ITypedList.GetListName Return "OrderDetails" End Function End Class Public Class OrderDetail Private prodID As Integer Private quantity_Renamed As Short Public ReadOnly Property ProductID() As Integer Get Return prodID End Get End Property Public ReadOnly Property Quantity() As Short Get Return quantity_Renamed End Get End Property Public Sub New(ByVal prodID As Integer, ByVal quantity As Integer) Me.prodID = prodID Me.quantity_Renamed = Convert.ToInt16(quantity) End Sub End Class |
创建数据
下列代码演示了如何创建并使用数据填充上面所声明的数据对象。
C# | 复制代码 |
---|---|
private SupplierCollection CreateData() { SupplierCollection suppliers = new SupplierCollection(); Supplier supplier = new Supplier("Exotic Liquids"); suppliers.Add(supplier); supplier.Add(CreateProduct(supplier.SupplierID, "Chai")); supplier.Add(CreateProduct(supplier.SupplierID, "Chang")); supplier.Add(CreateProduct(supplier.SupplierID, "Aniseed Syrup")); supplier = new Supplier("New Orleans Cajun Delights"); suppliers.Add(supplier); supplier.Add(CreateProduct(supplier.SupplierID, "Chef Anton's Cajun Seasoning")); supplier.Add(CreateProduct(supplier.SupplierID, "Chef Anton's Gumbo Mix")); supplier = new Supplier("Grandma Kelly's Homestead"); suppliers.Add(supplier); supplier.Add(CreateProduct(supplier.SupplierID, "Grandma's Boysenberry Spread")); supplier.Add(CreateProduct(supplier.SupplierID, "Uncle Bob's Organic Dried Pears")); supplier.Add(CreateProduct(supplier.SupplierID, "Northwoods Cranberry Sauce")); return suppliers; } static Random random = new Random(5); private Product CreateProduct(int supplierID, string productName) { Product product = new Product(supplierID, productName); product.OrderDetails.AddRange(new OrderDetail[] { new OrderDetail(product.ProductID, random.Next(0, 100)), new OrderDetail(product.ProductID, random.Next(0, 100)), new OrderDetail(product.ProductID, random.Next(0, 100)) }); return product; } |
Visual Basic | 复制代码 |
---|---|
Private Function CreateData() As SupplierCollection Dim suppliers As New SupplierCollection() Dim supplier As New Supplier("Exotic Liquids") suppliers.Add(supplier) supplier.Add(CreateProduct(supplier.SupplierID, "Chai")) supplier.Add(CreateProduct(supplier.SupplierID, "Chang")) supplier.Add(CreateProduct(supplier.SupplierID, "Aniseed Syrup")) supplier = New Supplier("New Orleans Cajun Delights") suppliers.Add(supplier) supplier.Add(CreateProduct(supplier.SupplierID, "Chef Anton's Cajun Seasoning")) supplier.Add(CreateProduct(supplier.SupplierID, "Chef Anton's Gumbo Mix")) supplier = New Supplier("Grandma Kelly's Homestead") suppliers.Add(supplier) supplier.Add(CreateProduct(supplier.SupplierID, "Grandma's Boysenberry Spread")) supplier.Add(CreateProduct(supplier.SupplierID, "Uncle Bob's Organic Dried Pears")) supplier.Add(CreateProduct(supplier.SupplierID, "Northwoods Cranberry Sauce")) Return suppliers End Function Private Shared random As New Random(5) Private Function CreateProduct(ByVal supplierID As Integer, ByVal productName As String) As Product Dim product As New Product(supplierID, productName) product.OrderDetails.AddRange(New OrderDetail() { _ New OrderDetail(product.ProductID, random.Next(0, 100)), _ New OrderDetail(product.ProductID, random.Next(0, 100)), _ New OrderDetail(product.ProductID, random.Next(0, 100))}) Return product End Function |
创建报表
下列代码演示了在运行时刻如何创建三层主/从报表,如何添加所有必需的带区和控件,并把报表绑定到由上面的代码创建的 ITypedList 数据源。
C# | 复制代码 |
---|---|
private XtraReport CreateReport() { XtraReport report = new XtraReport(); DetailBand detail = new DetailBand(); detail.Height = 30; report.Bands.Add(detail); DetailReportBand detailReport1 = new DetailReportBand(); report.Bands.Add(detailReport1); DetailBand detail1 = new DetailBand(); detail1.Height = 30; detailReport1.Bands.Add(detail1); DetailReportBand detailReport2 = new DetailReportBand(); detailReport1.Bands.Add(detailReport2); DetailBand detail2 = new DetailBand(); detail2.Height = 30; detailReport2.Bands.Add(detail2); report.DataSource = CreateData(); detailReport1.DataMember = "Products"; detailReport2.DataMember = "Products.OrderDetails"; detail.Controls.Add(CreateBoundLabel("CompanyName", Color.Gold, 0)); detail1.Controls.Add(CreateBoundLabel("Products.ProductName", Color.Aqua, 100)); detail2.Controls.Add(CreateBoundLabel("Products.OrderDetails.Quantity", Color.Pink, 200)); return report; } private XRLabel CreateBoundLabel(string dataMember, Color backColor, int offset) { XRLabel label = new XRLabel(); label.DataBindings.Add(new XRBinding("Text", null, dataMember)); label.BackColor = backColor; label.Location = new Point(offset, 0); return label; } |
Visual Basic | 复制代码 |
---|---|
Private Function CreateReport() As XtraReport Dim report As New XtraReport() Dim detail As New DetailBand() detail.Height = 30 report.Bands.Add(detail) Dim detailReport1 As New DetailReportBand() report.Bands.Add(detailReport1) Dim detail1 As New DetailBand() detail1.Height = 30 detailReport1.Bands.Add(detail1) Dim detailReport2 As New DetailReportBand() detailReport1.Bands.Add(detailReport2) Dim detail2 As New DetailBand() detail2.Height = 30 detailReport2.Bands.Add(detail2) report.DataSource = CreateData() detailReport1.DataMember = "Products" detailReport2.DataMember = "Products.OrderDetails" detail.Controls.Add(CreateBoundLabel("CompanyName", Color.Gold, 0)) detail1.Controls.Add(CreateBoundLabel("Products.ProductName", Color.Aqua, 100)) detail2.Controls.Add(CreateBoundLabel("Products.OrderDetails.Quantity", Color.Pink, 200)) Return report End Function Private Function CreateBoundLabel(ByVal dataMember As String, ByVal backColor As Color, ByVal offset As Integer) As XRLabel Dim label As New XRLabel() label.DataBindings.Add(New XRBinding("Text", Nothing, dataMember)) label.BackColor = backColor label.Location = New Point(offset, 0) Return label End Function |
查看运行结果
下列代码创建了一个报表,并显示了它的 打印预览。
C# | 复制代码 |
---|---|
private void button1_Click(object sender, EventArgs e) { XtraReport report = CreateReport(); report.ShowPreview(); } |
Visual Basic | 复制代码 |
---|---|
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles button1.Click Dim report As XtraReport = CreateReport() report.ShowPreview() End Sub |
在下面的插图中显示了结果报表。
Show Me |
---|
在 DevExpress Code Central 数据库中可以找到完整的示例项目,网址是 http://www.devexpress.com/example=E137。 取决于目标平台类型 (ASP.NET、WinForms 等),可以在线运行本示例,或者下载自动可执行的示例。 |