// 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 and the Product.Orders template does not contain DOCVARIABLE fields. So, further processing is not required.
        void richServerDetailProcessor_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e)
        {
            int currentProductID = GetID(e.Arguments[0].Value);

            if (currentProductID == -1)
            {
                return;
            }

            if (productID != currentProductID)
            {
                // Get data source that contains orders for the specified product and supplier.
                dataDetailedForOrders = (List <OrderDetail>)GetOrderDataFilteredbyProductAndSupplier(supplierID, currentProductID);
                productID             = currentProductID;
            }

            if (e.VariableName == "OrderDetails")
            {
                IRichEditDocumentServer richServerOrdersTemplate = mainRichEdit.CreateDocumentServer();
                RtfLoadHelper.Load("detaildetail.rtf", richServerOrdersTemplate);
                richServerOrdersTemplate.Options.MailMerge.DataSource = dataDetailedForOrders;

                IRichEditDocumentServer richServerDetailDetailProcessor = mainRichEdit.CreateDocumentServer();

                MailMergeOptions options = richServerOrdersTemplate.CreateMailMergeOptions();
                options.MergeMode = MergeMode.JoinTables;

                richServerOrdersTemplate.MailMerge(options, richServerDetailDetailProcessor);

                e.Value   = richServerDetailDetailProcessor;
                e.Handled = true;
            }
        }
        public MainPage()
        {
            InitializeComponent();

            tabControl.SelectionChanged += new DevExpress.Xpf.Core.TabControlSelectionChangedEventHandler(tabControl_SelectionChanged);

            // Subscribe to the CalculateDocumentVariable event that triggers the master-detail report generation
            resultRichEdit.CalculateDocumentVariable += new CalculateDocumentVariableEventHandler(resultRichEdit_CalculateDocumentVariable);

            // Load main template
            RtfLoadHelper.Load("main.rtf", mainRichEdit);

            // Create data sources for the project
            fakeDataSource = DataHelper.CreateFakeDataSource();
            DataHelper.CreateData();
            dataSuppliers           = DataHelper.Suppliers;
            dataDetailedForProducts = DataHelper.Products;
            dataDetailedForOrders   = DataHelper.OrderDetails;
        }
        // Third stage. For each Product ID create a detailed document that will be inserted in place of the DOCVARIABLE field.
        void richServerMasterProcessor_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e)
        {
            int currentSupplierID = GetID(e.Arguments[0].Value);

            if (currentSupplierID == -1)
            {
                return;
            }

            if (supplierID != currentSupplierID)
            {
                // Get data source that contains products for the specified supplier.
                dataDetailedForProducts = (List <Product>)GetProductsDataFilteredbySupplier(currentSupplierID);
                supplierID = currentSupplierID;
            }

            if (e.VariableName == "Product")
            {
                // Create a document container and load a document containing the Product header section (detail section)
                IRichEditDocumentServer richServerProductsTemplate = mainRichEdit.CreateDocumentServer();
                RtfLoadHelper.Load("detail.rtf", richServerProductsTemplate);
                // Create a text engine to process a document after the mail merge.
                IRichEditDocumentServer richServerDetailProcessor = mainRichEdit.CreateDocumentServer();

                // Specify data source for mail merge.
                richServerProductsTemplate.Options.MailMerge.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.
                MailMergeOptions options = richServerProductsTemplate.CreateMailMergeOptions();
                options.MergeMode = MergeMode.JoinTables;
                // Provide a procedure for further processing.
                richServerDetailProcessor.CalculateDocumentVariable += new CalculateDocumentVariableEventHandler(richServerDetailProcessor_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.
                richServerProductsTemplate.MailMerge(options, richServerDetailProcessor);
                richServerDetailProcessor.CalculateDocumentVariable -= richServerDetailProcessor_CalculateDocumentVariable;
                // Return the document to insert.
                e.Value = richServerDetailProcessor;
                // This setting is required for inserting e.Value into the source document. Otherwise it will be ignored.
                e.Handled = true;
            }
        }
 // 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 document container and load a document containing the Supplier header section (master section)
         IRichEditDocumentServer richServerSupplierTemplate = mainRichEdit.CreateDocumentServer();
         RtfLoadHelper.Load("supplier.rtf", richServerSupplierTemplate);
         // Create a text engine to process a document after the mail merge.
         IRichEditDocumentServer richServerMasterProcessor = mainRichEdit.CreateDocumentServer();
         // Provide a procedure for further processing
         richServerMasterProcessor.CalculateDocumentVariable += new CalculateDocumentVariableEventHandler(richServerMasterProcessor_CalculateDocumentVariable);
         // Create a merged document using the Supplier template. The document will contain DOCVARIABLE fields with ProductID arguments.
         // The CalculateDocumentVariable event for the richServerMasterProcessor fires.
         // Note that the data source for mail merge should be specified via the RichEditDocumentServer.Options.MailMerge.DataSource property.
         richServerSupplierTemplate.Options.MailMerge.DataSource = dataSuppliers;
         richServerSupplierTemplate.MailMerge(richServerMasterProcessor.Document);
         richServerMasterProcessor.CalculateDocumentVariable -= richServerMasterProcessor_CalculateDocumentVariable;
         // Return the document to insert in place of the DOCVARIABLE field.
         e.Value = richServerMasterProcessor;
         // Required. Otherwise e.Value will be ignored.
         e.Handled = true;
     }
 }