# Overview

> Plan mail merge in a WPF app: pre-shaped data, MailMerge created in code for the WPF TextControl, one document per record with DataRowMerged and printing.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Mail Merge and Reporting > Overview
- **3874 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/overview/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/overview/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/overview/llms-full.txt

---

Before a WPF application merges its first real template, a few decisions shape everything that follows: how the data is structured, whether the merge runs in the `TextControl` of the window or in the background, and whether all records end up in one document or in many. The sections below explain the reporting model of TX Text Control .NET for WPF and the `MailMerge` class behind it, with code for each of these decisions.

The [Mail Merge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/llms-full.txt) tutorials in Getting Started design a first template and merge it, and the [MailMerge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/overview/components/mailmerge/llms-full.txt) page of the Overview introduces the class. The examples here use the files of those tutorials: the template *invoice.docx* and the data *invoice.json* with the fields `Company`, `Name` and `InvoiceNumber` and the list `Items`.

### The Reporting Model

A template is an ordinary document without report bands. Users design it with the features of a word processor, such as tables, page columns, images and headers and footers, in a `TextControl` with the **Reporting** ribbon tab:

- **The text flows.** Merged content that makes a paragraph or a table longer breaks the lines and pages again, and a table continues on the next page.
- **Templates hold names, not data.** A template contains only the names of merge fields and merge blocks, so one template works with any data of the same structure.
- **Merge fields keep their formatting.** A merged value has the font, size and color the field has in the template.

The TX Words *Reporting* sample for WPF shows such a template merged: the invoice has the layout of its template, and the **Results** tab pages through the merged records and exports them with **Export Merge Result**:

![TX Text Control Words for WPF with a merged invoice, the Results tab with the buttons Exit, First Record, Previous Record, Next Record, Last Record and Export Merge Result, and the Export Merge Result dialog box](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/merge-results-tab.51e568c9.webp)

### Pre-Shaped Data

`MailMerge` doesn't query a database during the merge. Your code prepares the data in the hierarchy the document needs and passes it to a merge method; Text Control calls this *pre-shaped data*. Where the data comes from doesn't matter, as long as it arrives in this shape.

Internally, the hierarchy is converted into tables:

| In the data | In the template |
|---|---|
| A property of the root object, a column of the master table | A merge field of the same name, such as `Company` |
| A nested object, a related table with one row | A merge field with dot notation, such as `Customer.City` |
| An array, a collection or a related table | A merge block of the same name, such as `Items`, repeated for each record |

The records you pass form the *master table*, and the template is merged once for each of them: an array of 100 invoices creates 100 invoices. [Data Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/llms-full.txt) lists the kinds of data you can merge.

### Where the Merge Runs

`MailMerge` holds no document of its own. Its [TextComponent](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/textcomponent-property/llms-full.txt) property connects it to a `WPF.TextControl`, a Windows Forms `TextControl` or a `ServerTextControl`, which holds the template and, after the merge, the result. In a WPF application, two of them matter:

| Connected to | The template is | The result |
|---|---|---|
| The `TextControl` of the window | The document in the editor | Replaces the template in the editor, where the user sees it |
| A `ServerTextControl` | Loaded by your code, not visible | Stays in the `ServerTextControl` until your code saves or shows it |

Unlike the controls of the window, `MailMerge` is not declared in XAML: your code creates it, sets `TextComponent` and calls a merge method, usually in a `using` block that disposes of it while the merged document stays in the connected control. [Merge Directly in the Editor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/fields/#merge-directly-in-the-editor) in Getting Started merges the template of the window this way, and [Merge the Data](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/fields/#merge-the-data) merges in a `ServerTextControl` and loads the result into the editor. Either way, a DOCX template is loaded with `LoadSettings` that import its merge fields and merge blocks.

Whether it merges into a `TextControl` or a `ServerTextControl`, `MailMerge` uses the page size, margins and orientation of the connected control. Set [UseTemplateFormat](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/usetemplateformat-property/llms-full.txt) to `true` to keep those of the template; the default is `false`. To merge without touching the editor, use a [ServerTextControl](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/servertextcontrol/llms-full.txt), as in [Create One Document or One per Record](#create-one-document-or-one-per-record).

### What a Merge Processes

These elements of a template receive data:

| Element | What happens | Described in |
|---|---|---|
| `MERGEFIELD` fields | Replaced with the value of the same name | [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt) |
| `DATE` fields | Filled with the current date in the field's format | [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt) |
| `IF` fields | Insert one of two texts, depending on a comparison with the data | [Conditional Content](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/conditional-content/llms-full.txt) |
| `NEXT` and `NEXTIF` fields | Continue with the next record in the same document, always or on a condition, for example on a sheet of labels | The blog article [Sneak Peek Reporting X10: Creating Labels with NEXT Fields](https://www.textcontrol.com/blog/2013/09/17/sneak-peek-reporting-x10-creating-labels-with-next-fields/) |
| `INCLUDETEXT` fields | Replaced with another document, a subtemplate | [Subtemplates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/subtemplates/llms-full.txt) |
| Merge blocks | Repeated for each record of a list, also nested | [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt), [Nested Blocks and Master-Detail Reports](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/nested-blocks/llms-full.txt) |
| Image and barcode placeholders | Filled with an image or encode a value | [Images and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/images-barcodes/llms-full.txt) |
| Form fields | Left alone, preselected or replaced, depending on `FormFieldMergeType` | [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/#merge-form-fields) |

Headers and footers are merged as well.

### Create One Document or One per Record

The merge methods [MergeJsonData](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergejsondata-method/llms-full.txt), [MergeObjects](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergeobjects-method/llms-full.txt) and [Merge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/merge-method/llms-full.txt) take a second parameter, `append`. With `true`, the default, the records are merged into one document. With `false`, each record becomes a separate document, and the connected control holds only the last one at the end.

The [DataRowMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/datarowmerged-event/llms-full.txt) event occurs after each record, and its [MergedRow](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-datarowmergedeventargs/mergedrow-property/llms-full.txt) property holds that record's document in the internal TX Text Control format. This `Click` handler of a button named `splitButton` saves one PDF per invoice:

```csharp
using System.Collections.Generic;
using System.IO;
using System.Windows;
using TXTextControl;
using TXTextControl.DocumentServer;
```

```csharp
private void splitButton_Click(object sender, RoutedEventArgs e)
{
    List<byte[]> documents = new List<byte[]>();

    using (ServerTextControl tx = new ServerTextControl())
    {
        tx.Create();

        LoadSettings loadSettings = new LoadSettings
        {
            ApplicationFieldFormat = ApplicationFieldFormat.MSWord,
            LoadSubTextParts = true
        };

        tx.Load("invoice.docx", StreamType.WordprocessingML, loadSettings);

        using (MailMerge mailMerge = new MailMerge { TextComponent = tx })
        {
            // Collect the document of each record
            mailMerge.DataRowMerged += (s, args) => documents.Add(args.MergedRow);

            // false: a separate document for each record
            mailMerge.MergeJsonData(File.ReadAllText("invoice.json"), false);
        }
    }

    for (int i = 0; i < documents.Count; i++)
    {
        using (ServerTextControl document = new ServerTextControl())
        {
            document.Create();
            document.Load(documents[i], BinaryStreamType.InternalUnicodeFormat);
            document.Save($"invoice-{i + 1}.pdf", StreamType.AdobePDF);
        }
    }

    MessageBox.Show(this, $"{documents.Count} invoices created");
}
```

The merge runs in a `ServerTextControl`, so the template in the window stays as it is. `ServerTextControl` needs [Create](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/servertextcontrol/create-method/llms-full.txt) before any other call. Each collected byte array is loaded into a new instance and saved as *invoice-1.pdf*, *invoice-2.pdf* and so on; with the single invoice of *invoice.json*, that is one file until you add a second object to its array.

### Load, Save and Print With MailMerge

`MailMerge` can load the template and save and print the result by itself. The following handler merges *invoice.docx*, saves a PDF and prints the result on the printer selected in the WPF print dialog:

```csharp
using System.IO;
using System.Windows;
using System.Windows.Controls;
using TXTextControl;
using TXTextControl.DocumentServer;
```

```csharp
private void printButton_Click(object sender, RoutedEventArgs e)
{
    using (ServerTextControl tx = new ServerTextControl())
    {
        tx.Create();

        using (MailMerge mailMerge = new MailMerge { TextComponent = tx })
        {
            if (!mailMerge.LoadTemplate("invoice.docx", FileFormat.WordprocessingML))
            {
                MessageBox.Show(this, "The template could not be loaded.");
                return;
            }

            mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
            mailMerge.SaveDocument("invoice.pdf", StreamType.AdobePDF, new SaveSettings());

            // Let the user choose the printer
            PrintDialog printDialog = new PrintDialog();

            if (printDialog.ShowDialog() == true)
            {
                mailMerge.Print("Invoice", printDialog.PrintQueue.FullName, 1, true);
            }
        }
    }
}
```

- [LoadTemplate](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/loadtemplate-method/llms-full.txt) returns `false` if the template can't be loaded. The format is a value of [FileFormat](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/fileformat/enumeration/llms-full.txt): `MSWord`, `RichTextFormat`, `WordprocessingML` or `InternalUnicodeFormat`. [LoadTemplateFromMemory](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/loadtemplatefrommemory-method/llms-full.txt) loads a template from memory, and the [TemplateFile](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/templatefile-property/llms-full.txt) property takes a file name and deduces the format from its extension.
- [SaveDocument](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/savedocument-method/llms-full.txt) saves the merged document to a file, and [SaveDocumentToMemory](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/savedocumenttomemory-method/llms-full.txt) to a byte array or a string.
- [Print](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/print-method/llms-full.txt) with a document name, a printer name, the number of copies and whether to collate prints the merged document. `PrintDialog` is the WPF dialog of `System.Windows.Controls`, and `PrintQueue.FullName` is the name of the selected printer. Another overload takes a `System.Drawing.Printing.PrintDocument`.

`LoadTemplate` has no `LoadSettings` parameter. To control how a DOCX template's fields and blocks are imported, load it with `Load` and `LoadSettings`, as in the previous examples.

### Follow the Merge With Events

While it merges, `MailMerge` raises events such as [FieldMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/fieldmerged-event/llms-full.txt) for each field, [BlockRowMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/blockrowmerged-event/llms-full.txt) for each row of a merge block and `DataRowMerged` for each record. They are ordinary .NET events, not routed events, and your handlers can check the data, change the merged content or collect the results. [Merge Events](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/events/llms-full.txt) covers each of them.

### Next Steps

- [Data Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/llms-full.txt): JSON, business objects and DataSets.
- [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt): formats, date fields, fields without data and form fields.
- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt): repeat parts of a template for each record of a list.
- [Reporting Ribbon and WPF Dialog Boxes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/ribbon-dialogs/llms-full.txt): the WPF Reporting tab for designing templates.
- [Template Preview](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/template-preview/llms-full.txt): show users the merged result while they design.

---

## Nearby

- **Previous:** [Mail Merge and Reporting](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/llms-full.txt)
- **Next:** [Data Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/llms-full.txt)
