Bind a Report to a Collection that Implements the ITypedList Interface (Runtime Sample)
- 7 minutes to read
This tutorial demonstrates how to create a hierarchical master-detail data source at runtime and bind a report to it.
#Implement the ITypedList Interface to Data Objects
If a report’s data source consists of objects created at runtime, it should implement the ITypedList interface. The code below demonstrates how to implement the ITypedList interface for a 3-tier Supplier-Product-OrderDetail hierarchical data source.
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);
}
}
#Create Data
The following code demonstrates how to create the data objects declared in the previous section and populate them with data:
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;
}
#Create a Report
The following code demonstrates how to create a 3-tier master-detail report at runtime, add bands and controls to it, and bind the report to an ITypedList data source that was created in the previous sections.
using DevExpress.XtraReports.UI;
using DevExpress.XtraReports.Configuration;
// ...
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();
// Bind the label to data.
label.ExpressionBindings.Add(new ExpressionBinding("BeforePrint", "Text", dataMember));
label.BackColor = backColor;
label.Location = new Point(offset, 0);
return label;
}
#View the Result
The following code creates a report and shows its preview:
private void button1_Click(object sender, EventArgs e) {
XtraReport report = CreateReport();
// Show the report's print preview.
ReportPrintTool printTool = new ReportPrintTool(report);
printTool.ShowPreview();
}
The resulting report is shown in the image below.