原创|使用教程|编辑:龚雪|2017-08-22 16:00:55.000|阅读 500 次
概述:传统.NET界面有一个富文本控件RichTextBox,在DevExpress控件组里面也有一个同等的控件——RichEditControl
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
这个例子讲了一个比较老的方法。通过DOCVARIABLE字段,用RichEditDocumentServer创建主从文档。
该项目使用由DevExpress示例nwind.xml文件提供的的二级Categories - Products分层数据源。得到的文件如下所示:

DataClasses.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Linq;
namespace MasterDetailExample
{
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;
string orderID;
short quantity;
public int ProductID { get { return prodID; } }
public string OrderID { get { return orderID; } }
public short Quantity { get { return quantity; } }
public OrderDetail(int prodID, string orderID, int quantity) {
this.prodID = prodID;
this.orderID = orderID;
this.quantity = Convert.ToInt16(quantity);
}
}
}
DataHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MasterDetailExample
{
class DataHelper
{
public static 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);
public static Product CreateProduct(int supplierID, string productName)
{
Product product = new Product(supplierID, productName);
product.OrderDetails.AddRange(new OrderDetail[] {
new OrderDetail(product.ProductID, GetRandomString(), random.Next(0, 100)),
new OrderDetail(product.ProductID, GetRandomString(), random.Next(0, 100)),
new OrderDetail(product.ProductID, GetRandomString(), random.Next(0, 100)) });
return product;
}
public static List<int> CreateFakeDataSource()
{
List<int> result = new List<int>();
result.Add(0);
return result;
}
public static string GetRandomString()
{
string path = System.IO.Path.GetRandomFileName();
path = path.Replace(".", "");
return path;
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraRichEdit;
using DevExpress.XtraTab;
using DevExpress.XtraRichEdit.API.Native;
using System.Collections;
namespace MasterDetailExample
{
public partial class Form1 : Form
{
SupplierCollection ds;
ProductCollection dataDetailedForProducts;
OrderDetailCollection dataDetailedForOrders;
static List<int> fakeDataSource = DataHelper.CreateFakeDataSource();
int supplierID = -1;
int productID = -1;
public Form1()
{
InitializeComponent();
// Associate RichEditControls with TabPages
xtraTabPage1.Tag = mainRichEdit;
xtraTabPage2.Tag = suppllierRichEdit;
xtraTabPage3.Tag = productRichEdit;
xtraTabPage4.Tag = ordersRichEdit;
xtraTabControl1.SelectedPageChanged+=new TabPageChangedEventHandler(xtraTabControl1_SelectedPageChanged);
// Subscribe to the CalculateDocumentVariable event that triggers the master-detail report generation
resultRichEdit.CalculateDocumentVariable += new CalculateDocumentVariableEventHandler(resultRichEdit_CalculateDocumentVariable);
// Load main template
mainRichEdit.LoadDocument("main.rtf");
// Create project's data source
ds = DataHelper.CreateData();
// Load templates and specify data sources for RichEdit controls. These data sources facilitate inserting merge fields
//by using the Insert Merge Fields button in Ribbon UI.
suppllierRichEdit.LoadDocument("supplier.rtf");
suppllierRichEdit.Options.MailMerge.DataSource = ds;
productRichEdit.LoadDocument("detail.rtf");
productRichEdit.Options.MailMerge.DataSource = ds;
productRichEdit.Options.MailMerge.DataMember = "Products";
ordersRichEdit.LoadDocument("detaildetail.rtf");
ordersRichEdit.Options.MailMerge.DataSource = ds;
ordersRichEdit.Options.MailMerge.DataMember = "Products.OrderDetails";
// Display data using XtraGrid control.
gridControl1.DataSource = ds;
}
#region #startmailmerge
// Start the process by merging the main template into the document contained within the resultRichEdit control.
private void performMailMergeItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
// Since the main template contains no merge fields that require merge data, provide a mock data source.
// Otherwise, mail merge will not start.
mainRichEdit.Options.MailMerge.DataSource = fakeDataSource;
// Trigger the multistage process. After the first mailmerge the CalculateDocumentVariable event
//for the resultRichEdit control fires.
mainRichEdit.MailMerge(resultRichEdit.Document);
xtraTabControl1.SelectedTabPage = xtraTabPage5;
}
#endregion #startmailmerge
#region #secondstage
// Second stage. For each Supplier ID, create a detailed document that will be inserted in place of the DOCVARIABLE field.
void resultRichEdit_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e)
{
if (e.VariableName == "Supplier") {
// Create a text engine to process a document after the mail merge.
RichEditDocumentServer richServerMaster = new RichEditDocumentServer();
// Provide a procedure for further processing.
richServerMaster.CalculateDocumentVariable += richServerMaster_CalculateDocumentVariable;
// Create a merged document using the Supplier template. The document will contain DOCVARIABLE fields with ProductID arguments.
// The CalculateDocumentVariable event for the richServerMaster fires.
suppllierRichEdit.MailMerge(richServerMaster);
richServerMaster.CalculateDocumentVariable -= richServerMaster_CalculateDocumentVariable;
// Return the document to insert.
e.Value = richServerMaster.Document;
// Required to use e.Value. Otherwise it will be ignored.
e.Handled = true;
}
}
#endregion #secondstage
#region #thirdstage
// Third stage. For each Product ID, create a detailed document that will be inserted in place of the DOCVARIABLE field.
void richServerMaster_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e)
{
int currentSupplierID = GetID(e.Arguments[0].Value);
if (currentSupplierID == -1)
return;
if (supplierID != currentSupplierID) {
// Get the data source that contains products for the specified supplier.
dataDetailedForProducts = GetProductsDataFilteredbySupplier(currentSupplierID);
supplierID = currentSupplierID;
}
if (e.VariableName == "Product") {
// Create a text engine to process a document after the mail merge.
RichEditDocumentServer richServerDetail = new RichEditDocumentServer();
// Specify the data source for the mail merge.
MailMergeOptions options = productRichEdit.CreateMailMergeOptions();
options.DataSource = dataDetailedForProducts;
// Specify that the resulting table should be joined with the header table.
// Do not specify this option if calculated fields are not within table cells.
options.MergeMode = MergeMode.JoinTables;
// Provide a procedure for further processing.
richServerDetail.CalculateDocumentVariable += richServerDetail_CalculateDocumentVariable;
// Create a merged document using the Product template. The document will contain DOCVARIABLE fields with OrderID arguments.
// The CalculateDocumentVariable event for the richServerDetail fires.
productRichEdit.MailMerge(options, richServerDetail);
richServerDetail.CalculateDocumentVariable -= richServerDetail_CalculateDocumentVariable;
// Return the document to insert.
e.Value = richServerDetail.Document;
// This setting is required for inserting e.Value into the source document. Otherwise it will be ignored.
e.Handled = true;
}
}
#endregion #thirdstage
#region #fourthstage
// Fourth stage. For each Order ID, create a detailed document that will be inserted in place of the DOCVARIABLE field.
// This is the final stage. The Product.Orders template does not contain DOCVARIABLE fields, so further processing is not required.
void richServerDetail_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e)
{
int currentProductID = GetID(e.Arguments[0].Value);
if (currentProductID == -1)
return;
if (productID != currentProductID) {
// Get the data source that contains orders for the specified product.
// The data source is obtained from the data already filtered by Supplier.
dataDetailedForOrders = GetOrderDataFilteredbyProductAndSupplier(currentProductID);
productID = currentProductID;
}
if (e.VariableName == "OrderDetails") {
RichEditDocumentServer richServerDetailDetail = new RichEditDocumentServer();
MailMergeOptions options = ordersRichEdit.CreateMailMergeOptions();
options.DataSource = dataDetailedForOrders;
options.MergeMode = MergeMode.JoinTables;
ordersRichEdit.MailMerge(options, richServerDetailDetail);
e.Value = richServerDetailDetail.Document;
e.Handled = true;
}
}
#endregion #fourthstage
#region Helper Methods
void xtraTabControl1_SelectedPageChanged(object sender, TabPageChangedEventArgs e)
{
// Specify a new target for the Ribbon interface - the RichEditControl that is currently active.
RichEditControl richEditControl = (RichEditControl)xtraTabControl1.SelectedTabPage.Tag;
richEditBarController1.RichEditControl = richEditControl;
}
protected internal virtual ProductCollection GetProductsDataFilteredbySupplier(int supplierID)
{
ProductCollection products = new ProductCollection();
foreach (Supplier s in ds) {
if (s.SupplierID == supplierID) {
products.AddRange(s.Products);
}
}
return products;
}
protected internal virtual OrderDetailCollection GetOrderDataFilteredbyProductAndSupplier(int productID)
{
OrderDetailCollection orders = new OrderDetailCollection();
foreach (Product p in dataDetailedForProducts) {
if (p.ProductID == productID) {
orders.AddRange(p.OrderDetails);
}
}
return orders;
}
protected internal virtual int GetID(string value)
{
int result;
if (Int32.TryParse(value, out result))
return result;
return -1;
}
#endregion Helper Methods
}
}
想要速成DevExpress大师?秘籍在这里→
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@ke049m.cn