# Images and Barcodes

> Fill image and barcode placeholders in WPF: TXTextControl.Image, the WPF TXBarcodeControl, UpperTextLength, Base64 and SVG data, ImageMerged and BarcodeMerged.

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

---

Merged documents often need more than text from the data: a customer's logo, a product photo or a QR code that encodes the invoice number. In a template, each of these is a placeholder, an image or a barcode with a name. `MailMerge` fills every placeholder whose name matches a field of the data and leaves its size and position as designed. The sections below create placeholders in the WPF editor and in code, merge images from Base64 data, files and SVG, merge values into barcodes and check those values beforehand.

The invoice of [Merge Data into Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/fields/llms-full.txt) gets a logo and a QR code for its invoice number. For images and barcodes added without a merge, see [Images and Shapes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/images-shapes/llms-full.txt) and [Charts and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-processing/charts-barcodes/llms-full.txt).

### How Placeholders Work

An image or barcode becomes a placeholder through its name, which matches a field of the data:

- **Image data** can be a byte array, a `System.Drawing.Image`, a Base64 string, a hexadecimal string that starts with `X'`, the name of an image file or, since version 32.0 SP3, SVG markup as plain XML text.
- **Size and layout stay.** A merged image is scaled to the width of the placeholder and keeps its position and text flow.
- **Barcodes** keep their type, size and position, and only the encoded text changes.
- **Inside a merge block**, placeholders are merged once per record, for example a photo in each product row.
- **Names** follow the rules of merge field names, dot notation for related data included.
- **Image placeholders without data** stay in the document unless [RemoveEmptyImages](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyimages-property/llms-full.txt) is `true`; the default is `false`.

Save templates with placeholders in the TX Text Control format, here as *invoice.tx*, as Text Control's samples do.

Both kinds of placeholders can fill one document. The following packing slip was merged from JSON data: the QR code at the top and the linear barcode in each row of the item block received their values from the data. The blog article [Enhancing Documents with QR Codes and Barcodes in .NET C#: A Comprehensive Guide](https://www.textcontrol.com/blog/2024/07/11/enhancing-documents-with-qr-codes-and-barcodes-in-net-csharp-a-comprehensive-guide/) shows its template and data:

![A merged packing slip with a QR code in the upper right corner and a linear barcode at the end of each of its eight item rows.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/packing-slip-barcodes.4a025714.webp)

### Create Placeholders With the Ribbon

The **Insert** tab of the WPF ribbon inserts images and barcodes. To make one of them a placeholder, select it and type its name into the object name box of the **Frame Formatting** tab, the [RibbonFrameLayoutTab](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/ribbonframelayouttab/llms-full.txt), which edits images, text frames, drawings and barcodes. Connect that tab to the `TextControl` in XAML as described in [Ribbon](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/ribbon-ui/ribbon/llms-full.txt).

With a data source loaded into the Reporting tab, the **Merge Fields** group offers **Select Frame Data Column** while an image or barcode is selected, so that users pick the name from the columns of the data instead of typing it.

### Create Placeholders in Code

A placeholder is a frame with a [Name](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/framebase/name-property/llms-full.txt). The following handlers insert a logo placeholder and a QR code at the input position of `textControl1`. Add `using TXTextControl.Barcode;`, `using TXTextControl.DataVisualization;` and `using TXTextControl.WPF.Barcode;` to *MainWindow.xaml.cs*:

```csharp
private void insertLogoPlaceholderButton_Click(object sender, RoutedEventArgs e)
{
    // 4 is the filter index of PNG files
    TXTextControl.Image placeholder = new TXTextControl.Image("placeholder.png", 4);

    // Insert the image inline at the input position
    textControl1.Images.Add(placeholder, -1);

    // The name connects the placeholder with the data
    placeholder.Name = "Logo";
}

private void insertQrCodeButton_Click(object sender, RoutedEventArgs e)
{
    // The WPF barcode control of TXTextControl.WPF.Barcode
    TXBarcodeControl qrCode = new TXBarcodeControl
    {
        BarcodeType = BarcodeType.QRCode,
        // The size of the code is calculated for 12 characters
        UpperTextLength = 12,
        Text = "INV-0000-000"
    };

    BarcodeFrame barcodeFrame = new BarcodeFrame(qrCode)
    {
        // The name connects the barcode with the data
        Name = "InvoiceNumber",
        Size = new System.Drawing.Size(1440, 1440) // 1 inch in twips
    };

    textControl1.Barcodes.Add(barcodeFrame, -1);
}
```

The code works as follows:

- The [Image constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/image/constructor/llms-full.txt) with a file name and filter index loads the placeholder picture. The overloads that take a `System.Drawing.Image` or a `MemoryStream` make the compiler ask for the *System.Drawing.Common* package in a WPF project for .NET; the file overload doesn't. The full name `TXTextControl.Image` avoids a clash with the WPF `Image` control of `System.Windows.Controls`.
- [ImageCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/imagecollection/add-method/llms-full.txt) with `-1` inserts the image at the input position. Its size is the width of every merged image.
- The QR code is inserted like any barcode, a WPF [TXBarcodeControl](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf-barcode/txbarcodecontrol/llms-full.txt) in a [BarcodeFrame](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-datavisualization/barcodeframe/llms-full.txt), as [Insert a Barcode From Code](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/charts-barcodes/#insert-a-barcode-from-code) explains; the Windows Forms class of the same name can't be used here. What makes it a placeholder is the `Name` of the frame, and its `Text` is shown only until the merge.

Because a barcode must not push the surrounding text away, its frame keeps its size and the code inside scales with the text: [UpperTextLength](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf-barcode/txbarcodecontrol/uppertextlength-property/llms-full.txt) is the length at which the code fills the frame. Set it to the longest value your data holds, before `Text`, as the blog article [Understanding the UpperTextLength of Barcodes in TX Text Control X9](https://www.textcontrol.com/blog/2013/05/09/understanding-the-uppertextlength-of-barcodes-in-tx-text-control-x9/) explains.

### Add the Image Data

In JSON, an image travels as a Base64 string. Add a `Logo` property with the Base64 data of a PNG image to *invoice.json*:

```json
[
  {
    "Company": "Contoso Ltd.",
    "Name": "Jane Miller",
    "InvoiceNumber": "INV-1001",
    "Logo": "iVBORw0KGgoAAAANSUhEUgAA...",
    "Items": [
      { "Description": "Consulting", "Quantity": 2, "Price": 150.00 },
      { "Description": "Training", "Quantity": 1, "Price": 480.00 }
    ]
  }
]
```

Replace the shortened value with the complete Base64 string of your image; `InvoiceNumber` fills the QR code. A file name as value, such as `"Logo": "logo.png"`, makes `MailMerge` load the file from the folder of [SearchPath](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/searchpath-property/llms-full.txt), or from the root directory when the search path is empty. SVG markup is passed as it is, without Base64 encoding; the blog article [Service Pack 3: MailMerge Supports SVG Images](https://www.textcontrol.com/blog/2024/04/29/service-pack-3-mailmerge-supports-svg-images/) has an example.

### Merge Images and Barcodes

This handler merges *invoice.tx*, removes empty image placeholders and loads the result into the editor. It needs `using System;`, `using System.IO;` and `using TXTextControl.DocumentServer;`:

```csharp
private void mergeImagesButton_Click(object sender, RoutedEventArgs e)
{
    byte[] result;

    using (ServerTextControl tx = new ServerTextControl())
    {
        tx.Create();
        tx.Load("invoice.tx", StreamType.InternalUnicodeFormat);

        using (MailMerge mailMerge = new MailMerge
        {
            TextComponent = tx,
            // Remove placeholders the data has no image for
            RemoveEmptyImages = true,
            // Image file names in the data are searched here
            SearchPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images")
        })
        {
            mailMerge.ImageMerged += (s, args) =>
            {
                if (args.Merged && args.Name == "Logo")
                {
                    args.DescriptiveText = "Company logo";
                }
            };

            mailMerge.BarcodeMerged += (s, args) =>
                System.Diagnostics.Debug.WriteLine("Barcode merged: " + args.BarcodeFrame.Name);

            mailMerge.MergeJsonData(File.ReadAllText("invoice.json"));
        }

        tx.Save(out result, BinaryStreamType.InternalUnicodeFormat);
    }

    textControl1.Load(result, BinaryStreamType.InternalUnicodeFormat);
}
```

The code works as follows:

- [ImageMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/imagemerged-event/llms-full.txt) occurs for each image placeholder, with the [Name](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-imagemergedeventargs/name-property/llms-full.txt) of the placeholder, whether it was [Merged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-imagemergedeventargs/merged-property/llms-full.txt) and, in a block, the [MergeBlockName](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-imagemergedeventargs/mergeblockname-property/llms-full.txt).
- [DescriptiveText](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-imagemergedeventargs/descriptivetext-property/llms-full.txt) replaces the descriptive text of the merged image. The [Image](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-imagemergedeventargs/image-property/llms-full.txt) property is a `System.Drawing.Image`, which a WPF project for .NET uses through the *System.Drawing.Common* package.
- [BarcodeMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/barcodemerged-event/llms-full.txt) follows each merged barcode, and [BarcodeMergedEventArgs](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-barcodemergedeventargs/llms-full.txt) holds its [BarcodeFrame](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge-barcodemergedeventargs/barcodeframe-property/llms-full.txt).

The editor then shows the invoice with the logo in the size of the placeholder and a QR code for *INV-1001*.

### Check Barcode Values

A value from the data may contain characters or have a length that a barcode type can't encode. The static methods of the WPF `TXBarcodeControl` check it before the merge:

```csharp
string invoiceNumber = "INV-1001";

if (!TXBarcodeControl.IsTextValid(BarcodeType.QRCode, invoiceNumber, out string errorMessage))
{
    MessageBox.Show(this, "Invalid value: " + errorMessage);
}
```

[IsTextValid](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf-barcode/txbarcodecontrol/istextvalid-method/llms-full.txt) returns `false` and an error message for an invalid value. [GetMinimumTextLength](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf-barcode/txbarcodecontrol/getminimumtextlength-method/llms-full.txt) and [GetMaximumTextLength](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf-barcode/txbarcodecontrol/getmaximumtextlength-method/llms-full.txt) return the allowed lengths of a type. [Insert a Barcode From Code](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/charts-barcodes/#insert-a-barcode-from-code) lists the 20 values of [BarcodeType](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-barcode/barcodetype/enumeration/llms-full.txt).

### Image Merge Fields

Older templates merge images into merge fields named with the prefix `image:`, such as `image:Logo`. `MailMerge` still processes them, but their event, [ImageFieldMerged](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/imagefieldmerged-event/llms-full.txt), is marked obsolete in the assembly, and using it causes a compiler warning. New templates use named placeholders and `ImageMerged`.

### Next Steps

- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt): repeat images and barcodes for each record.
- [Data Sources](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/llms-full.txt): the data that carries images and values.
- [Charts and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/charts-barcodes/llms-full.txt): barcodes in the WPF editor.
- The blog article [Merging Barcodes with JSON Data in C#](https://www.textcontrol.com/blog/2022/02/14/merging-barcodes-with-json-data-in-csharp/): a QR code filled from JSON data.

---

## Nearby

- **Previous:** [Subtemplates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/subtemplates/llms-full.txt)
- **Next:** [Conditional Content](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/conditional-content/llms-full.txt)
