# Conditional Content

> Conditional content in WPF mail merge: IF fields created with IfField, blocks for optional sections, BlockMergingCondition, IncludeTextMerging and FieldMerged.

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

---

Should an invoice remind the customer to pay, or thank them for paying? Should a contract contain the non-compete clause? One template can answer such questions from the data. With TX Text Control, most rules for conditional content are part of the template, where users of the Reporting tab see and maintain them, and the merge code of your WPF application stays the same: `IF` fields insert one of two texts, merge blocks include or remove sections, conditions and filters act on records, and `MailMerge` events cover what templates can't express.

All examples merge the invoice template *invoice.docx* of [Merge Data into Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/fields/llms-full.txt) with *invoice.json*. Leaving out single rows of a block is the subject of [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/sorting-filtering/llms-full.txt).

### Choose a Technique

| To | Use | Where the rule lives |
|---|---|---|
| Insert one of two texts depending on a value | An `IF` field | Template |
| Include a section only when its data exists | A merge block bound to an object or an array | Template |
| Merge a nested block only when its parent record meets a condition | The block's merging condition | Template |
| Leave out single rows of a block | Filter instructions of the block | Template |
| Include or leave out a subtemplate | An `INCLUDETEXT` field and the `IncludeTextMerging` event | Template and code |
| Change a merged value with your own logic | The `FieldMerged` event | Code |

### Insert IF Fields

An `IF` field compares the value of a merge field with another value and inserts the text for true or the text for false. Its MS Word field code reads `IF Expression1 Operator Expression2 TrueText FalseText`; `Expression1` is the name of a merge field, and the operator is equal to, not equal to, greater than, less than, greater than or equal to or less than or equal to.

For the examples, *invoice.json* gets an `AmountDue` and a `DueDate`:

```json
[
  {
    "Company": "Contoso Ltd.",
    "Name": "Jane Miller",
    "InvoiceNumber": "INV-1001",
    "AmountDue": 780.00,
    "DueDate": "2026-10-31",
    "Items": [
      { "Description": "Consulting", "Quantity": 2, "Price": 150.00 },
      { "Description": "Training", "Quantity": 1, "Price": 480.00 }
    ]
  }
]
```

Users of the WPF Reporting tab insert the field with **IF** in the **Insert Special Field** drop-down of the **Merge Fields** group and fill in the field name, the comparison and the two texts. Your code creates it with [IfField](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/llms-full.txt). Add a button with `Click="insertIfFieldButton_Click"` to *MainWindow.xaml*, `using TXTextControl.DocumentServer.Fields;` to *MainWindow.xaml.cs* and this handler:

```csharp
private void insertIfFieldButton_Click(object sender, RoutedEventArgs e)
{
    IfField ifField = new IfField
    {
        Expression1 = "AmountDue",   // the name of a merge field
        Operator = IfField.RelationalOperator.GreaterThan,
        Expression2 = "0",
        TrueText = "Please pay the amount due by the due date.",
        FalseText = "Thank you, this invoice has been paid."
    };

    textControl1.ApplicationFields.Add(ifField.ApplicationField);
}
```

The code works as follows:

- [Expression1](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/expression1-property/llms-full.txt) is the merge field that is compared, and [Expression2](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/expression2-property/llms-full.txt) the value it is compared with.
- [Operator](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/operator-property/llms-full.txt) takes `Equals`, `NotEqual`, `LessThan`, `GreaterThan`, `GreaterThanOrEqualTo` or `LessThanOrEqualTo`.
- [TrueText](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/truetext-property/llms-full.txt) and [FalseText](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/falsetext-property/llms-full.txt) are the two texts.
- [DataSourceCulture](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-fields/iffield/datasourceculture-property/llms-full.txt) is the culture for comparing numbers; by default, the culture of the current thread.

Since `AmountDue` is 780.00, the merged invoice asks for payment, in the formatting of the field. Inside a merge block, the field is evaluated per record. Load templates with `ApplicationFieldFormat.MSWord` so that `IF` fields from DOCX files are imported as fields.

### Include Optional Sections

A block bound to a single nested object is merged once when the object exists. When the data lacks the object, or a block's array is empty or missing, the block disappears with its content, because [RemoveEmptyBlocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyblocks-property/llms-full.txt) is `true` by default. Such a block can hold complete clauses, tables or images.

In a contract template, each optional clause is a block named like an object of the data:

```json
[
  {
    "company": "Acme Corporation",
    "section_term": { "months": 24 },
    "section_compete": { "months": 12 }
  }
]
```

Without `section_compete` in a contract's data, the non-compete clause is left out and the text after it moves up. The blog article [Generating Dynamic NDAs Using TX Text Control MailMerge in C# .NET](https://www.textcontrol.com/blog/2025/04/08/generating-dynamic-ndas-using-tx-text-control-mailmerge-in-csharp-dotnet/) builds an agreement from such sections, and [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt) shows how blocks are inserted.

A header row outside a removed block stays behind; to remove a whole table, put its header row into the block.

### Merge a Block Only for Matching Parent Records

A nested block can depend on its parent record, for example articles listed only for orders above an amount. The condition is the block's [BlockMergingCondition](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/mergeblockinfo/blockmergingcondition-property/llms-full.txt), stored in the template, so the merge code doesn't change. [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/sorting-filtering/#merge-a-block-only-for-matching-parent-rows) sets one; the blog article [MailMerge: Rendering Conditional Table Rows](https://www.textcontrol.com/blog/2022/02/17/mailmerge-rendering-conditional-table-rows/) adds a note row only for products that aren't available.

### Include Subtemplates Depending on Your Code

The [IncludeTextMerging](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/includetextmerging-event/llms-full.txt) event occurs for each `INCLUDETEXT` field, and an empty document assigned in its handler leaves the subtemplate out. Here, a field of the window decides whether *terms.docx* is included; *MainWindow.xaml.cs* needs `using TXTextControl.DocumentServer;` for the event arguments:

```csharp
private bool includeTerms = false; // decided by your application

private void MailMerge_IncludeTextMerging(object sender, MailMerge.IncludeTextMergingEventArgs e)
{
    if (includeTerms || !e.Filename.EndsWith("terms.docx"))
    {
        return;
    }

    // An empty document leaves the subtemplate out
    using (ServerTextControl empty = new ServerTextControl())
    {
        empty.Create();

        byte[] data;
        empty.Save(out data, BinaryStreamType.InternalUnicodeFormat);
        e.IncludeTextDocument = data;
    }
}
```

Attach the handler with `mailMerge.IncludeTextMerging += MailMerge_IncludeTextMerging;` before calling the merge method. [Subtemplates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/subtemplates/llms-full.txt) covers `INCLUDETEXT` fields and the search path. For a decision per record, the blog article [MailMerge: Conditional INCLUDETEXT Fields](https://www.textcontrol.com/blog/2015/01/08/mailmerge-conditional-includetext-fields/) tracks the current record in the `DataRowMerged` event and reads a flag from the data.

### Change a Merged Value in Code

When the rule is too complex for a template, handle [FieldMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/fieldmerged-event/llms-full.txt). [DataRow](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/datarow-property/llms-full.txt) gives the whole record, so the text of one field can depend on another. With `using System;` and `using System.Globalization;`, this handler shows "Paid" instead of the due date when nothing is due:

```csharp
mailMerge.FieldMerged += (s, args) =>
{
    // Show "Paid" instead of the due date when nothing is due
    if (args.MailMergeFieldAdapter is MergeField mergeField &&
        mergeField.Name == "DueDate" &&
        args.DataRow != null &&
        Convert.ToDecimal(args.DataRow["AmountDue"], CultureInfo.InvariantCulture) == 0)
    {
        mergeField.ApplicationField.Text = "Paid";
    }
};
```

`MailMergeFieldAdapter` is the name of the property in the compiled assembly; the reference describes the event arguments on the page of [FieldMergedEventArgs](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-fieldmergedeventargs/llms-full.txt). [Merge Events](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/events/llms-full.txt) covers the event in full.

### Remove What Stays Empty

Five properties of `MailMerge` remove what optional content leaves behind:

| Property | Removes | Default |
|---|---|---|
| [RemoveEmptyFields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyfields-property/llms-full.txt) | Merge fields without data | `true` |
| [RemoveEmptyBlocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyblocks-property/llms-full.txt) | Merge blocks without data, with their content | `true` |
| [RemoveEmptyLines](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptylines-property/llms-full.txt) | Lines that are empty after the merge | `false` |
| [RemoveEmptyImages](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyimages-property/llms-full.txt) | Image placeholders without data | `false` |
| [RemoveTrailingWhitespace](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removetrailingwhitespace-property/llms-full.txt) | Trailing whitespace, before the document is saved | `true` |

### Conditional Instructions Are for Forms

The *conditional instructions* of TX Text Control change form fields while a user fills in a form, for example by disabling a drop-down list while another field has no value. They work in the editor, not in the merge; [Form Fields and Conditional Instructions](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/form-fields/llms-full.txt) describes them for WPF.

### Next Steps

- [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/sorting-filtering/llms-full.txt): filter the rows of a block and set merging conditions.
- [Subtemplates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/subtemplates/llms-full.txt): reusable sections included with `INCLUDETEXT` fields.
- [Merge Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/fields/llms-full.txt): formats and text for fields without data.
- [Template Preview](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/template-preview/llms-full.txt): check the variants of a template while designing.

---

## Nearby

- **Previous:** [Images and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/images-barcodes/llms-full.txt)
- **Next:** [Sorting and Filtering](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/sorting-filtering/llms-full.txt)
