# Signature Fields and Signature Appearance

> Give each named field of a WPF TextControl its own DigitalSignature, pick its SignatureImage in an OpenFileDialog, set its export format and draw an SVG stamp.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Digital Signatures > Signature Fields and Signature Appearance
- **4625 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signature-fields/llms-full.txt

---

A signature field marks the place in a document where a signature belongs: a frame with a name, an optional image and the data of the person who is expected to sign. When the document is saved as PDF, TX Text Control can sign every named field with its own certificate, and the field's image becomes the visible face of that signature. In a WPF application, the fields live in the document of the `TextControl`, so your code signs what users prepared in the editor. Signing the fields, giving them an image, generating a signature appearance with name and date and the resulting PDF are covered below.

Inserting signature fields with the ribbon, and editing their layout and signer data, belongs to [Signature Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/signature-fields/llms-full.txt) in Document Editor. [Sign a Signature Field](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/pdf/sign/#sign-a-signature-field) in Getting Started inserts and signs a first field in code.

### What a Signature Field Holds

[SignatureField](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefield/llms-full.txt) derives from `FrameBase`, like images and text frames, and is positioned the same way. Three of its parts matter for signing:

- **The name.** [Name](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/framebase/name-property/llms-full.txt) associates the field with a certificate, so a field without a name can't be signed. [ID](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/framebase/id-property/llms-full.txt) is an optional number of your own.
- **The image.** [Image](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefield/image-property/llms-full.txt) is a [SignatureImage](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/llms-full.txt), or `null` while the field has none. It can be set when the document is designed or when it's signed.
- **The signer data.** [SignerData](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefield/signerdata-property/llms-full.txt) describes the suggested signer: name, title, address, contact information and the reason for signing, in the order of its [constructor](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signerdata/constructor/llms-full.txt). Every value can be `null` or empty.

The fields of the editor's document are in [WPF.TextControl.SignatureFields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/signaturefields-property/llms-full.txt). How to insert, find and remove them, and which formats keep them, is described in [Signature Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/signature-fields/llms-full.txt) in Document Editor; [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signaturefieldcollection/getitem-method/llms-full.txt) returns `null` when no field matches. Signature lines of MS Word documents are loaded as signature fields with their signer data, as the blog article [Importing and Processing Signature Fields from MS Word in C#](https://www.textcontrol.com/blog/2023/01/06/importing-and-processing-signature-fields-from-ms-word-in-csharp/) shows.

The samples below need these `using` directives in *MainWindow.xaml.cs*:

```csharp
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Windows;
using Microsoft.Win32;
using TXTextControl;
```

### Sign the Fields of the Document

For each named field, create a [DigitalSignature](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/digitalsignature/llms-full.txt) with the field's name as the third constructor parameter, and pass all of them in [SaveSettings.SignatureFields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/savesettings/signaturefields-property/llms-full.txt):

```csharp
private void signFieldsButton_Click(object sender, RoutedEventArgs e)
{
    X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12FromFile(
        "certificate.pfx", "123", X509KeyStorageFlags.Exportable);

    List<DigitalSignature> signatures = new List<DigitalSignature>();

    foreach (SignatureField field in textControl1.SignatureFields)
    {
        // A certificate can only be associated with a named field
        if (string.IsNullOrEmpty(field.Name))
        {
            continue;
        }

        signatures.Add(new DigitalSignature(certificate, "", field.Name));
    }

    if (signatures.Count == 0)
    {
        MessageBox.Show(this, "The document has no named signature field.");
        return;
    }

    SaveSettings saveSettings = new SaveSettings()
    {
        SignatureFields = signatures.ToArray()
    };

    textControl1.Save("signed-fields.pdf", StreamType.AdobePDF, saveSettings);
}
```

The code works as follows:

- The loop visits every field of the document in the editor and skips those without a name.
- The second parameter of each `DigitalSignature` is the URL of a time server, or an empty string for the computer's date and time; see [Timestamp Configuration](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/timestamps/llms-full.txt).
- One save applies all signatures. Different signers and certificates are covered in [Multiple Signatures](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/llms-full.txt).

`X509CertificateLoader` is part of .NET 9 and higher. For .NET 8 and the .NET Framework, see [Load the Certificate From a PFX File](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/certificates/#load-the-certificate-from-a-pfx-file).

### Add a Signature Image

The [SignatureImage constructors](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/constructor/llms-full.txt) take an image in three forms:

| Constructor | Creates the image from |
|---|---|
| `SignatureImage(string fileName, int filterIndex)` | An image file. The filter index is its format: `1` BMP, `2` TIF, `3` WMF, `4` PNG, `5` JPG, `6` GIF, `7` EMF or `8` SVG. |
| `SignatureImage(MemoryStream memoryStream)` | Image data in a stream, such as a generated SVG image |
| `SignatureImage(System.Drawing.Image image)` | A `System.Drawing.Image`. WPF images, such as a `BitmapSource`, aren't accepted; save them to a stream instead. |

The following handler lets the user choose an image file for the signature field selected in the editor. It uses the WPF `OpenFileDialog` of `Microsoft.Win32`, whose `ShowDialog` returns a `bool?`:

```csharp
private void addSignatureImageButton_Click(object sender, RoutedEventArgs e)
{
    // The signature field that is selected in the editor, or null
    SignatureField field = textControl1.SignatureFields.GetItem();

    if (field == null)
    {
        MessageBox.Show(this, "Select a signature field first.");
        return;
    }

    OpenFileDialog dialog = new OpenFileDialog();
    dialog.Filter = "PNG images (*.png)|*.png|SVG images (*.svg)|*.svg";

    if (dialog.ShowDialog(this) == true)
    {
        // Filter index 4 is PNG, 8 is SVG
        int filterIndex = dialog.FilterIndex == 1 ? 4 : 8;
        field.Image = new SignatureImage(dialog.FileName, filterIndex);
    }
}
```

`null` as the value of `Image` removes the image again. To react when the user clicks or selects a field, for example to offer this dialog box, use the events described in [Handle Signature Field Events](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/signature-fields/#handle-signature-field-events).

#### Control How the Signature Image Is Saved

A `SignatureImage` keeps its origin: [FileName](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/filename-property/llms-full.txt) is the file and path it was loaded from, and [FilterIndex](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/filterindex-property/llms-full.txt) its format, with the numbers of the constructor table above. Five more properties decide how the image is written when the document is saved:

| Property | Sets |
|---|---|
| [SaveMode](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/savemode-property/llms-full.txt) | Whether the image is stored with its data (`SaveAsData`), as a reference to its file (`SaveAsFileReference`) or as [SaveSettings.ImageSaveMode](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/savesettings/imagesavemode-property/llms-full.txt) specifies (`Auto`). Without a setting, an image loaded from a file is stored as a file reference, and one from a stream or the clipboard with its data. |
| [ExportFilterIndex](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/exportfilterindex-property/llms-full.txt) | The format the image is saved in, numbered from 1 as in [ImageCollection.ExportFilters](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/imagecollection/exportfilters-property/llms-full.txt): `1` BMP, `2` WMF, `3` PNG, `4` JPG, `5` EMF, `6` TIF or `7` GIF. `0` keeps the original format. |
| [ExportFileName](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/exportfilename-property/llms-full.txt) | The file name of the image when the document is saved. An empty string uses the original name or one built from the document's file name, a number and the extension, such as *contract\_1.png*. |
| [ExportCompressionQuality](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/exportcompressionquality-property/llms-full.txt) | The quality of a lossy compression, from 1 to 100. `0`, the default, uses [SaveSettings.ImageCompressionQuality](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/savesettings/imagecompressionquality-property/llms-full.txt). |
| [ExportMaxResolution](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/signatureimage/exportmaxresolution-property/llms-full.txt) | The maximum resolution in dots per inch; a larger image is reduced. `0`, the default, uses [SaveSettings.ImageMaxResolution](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol/savesettings/imagemaxresolution-property/llms-full.txt). |

The export numbers differ from the import numbers: PNG is `4` for `FilterIndex` and `3` for `ExportFilterIndex`. The following lines make the image of the selected field travel with the document as PNG data, at no more than 300 dots per inch:

```csharp
SignatureField field = textControl1.SignatureFields.GetItem();

if (field?.Image != null)
{
    // Store the image data, not a reference to the original file
    field.Image.SaveMode = ImageSaveMode.SaveAsData;
    field.Image.ExportFilterIndex = 3; // PNG
    field.Image.ExportMaxResolution = 300;
}
```

Users set the same options in the dialog box of the field. [SignatureFieldLayoutDialog](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/textcontrol/signaturefieldlayoutdialog-method/llms-full.txt) opens the layout, size and text distances of the selected signature field, and `SignatureFieldLayoutDialog(2)` its third tab with the saving attributes of the signature image, which is available only when the field has an image. [Built-in Dialog Boxes](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/ribbon-ui/dialog-boxes/llms-full.txt) lists the other dialog boxes.

### Create a Signature Appearance

Whatever the image of a field shows is the appearance of its signature. A common choice is a stamp with the signer's name, the reason and the date, possibly next to a handwritten signature. Since `SignatureImage` reads an SVG image from a stream, your code can generate the stamp from the signer data of the field. The following methods do this for a field named `txsign` and sign it:

```csharp
private void SetSignatureStamp(SignatureField field)
{
    SignerData signer = field.SignerData;
    string name = SecurityElement.Escape(signer?.Name ?? "");
    string reason = SecurityElement.Escape(signer?.Reason ?? "");

    // An SVG image with a frame, the signer's name, the reason and the date
    string svg =
        "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"300\" height=\"100\">" +
        "<rect x=\"1\" y=\"1\" width=\"298\" height=\"98\" fill=\"none\" stroke=\"#1F4E79\" stroke-width=\"2\"/>" +
        "<text x=\"12\" y=\"30\" font-family=\"Arial\" font-size=\"14\" fill=\"#1F4E79\">Digitally signed by</text>" +
        $"<text x=\"12\" y=\"54\" font-family=\"Arial\" font-size=\"18\" font-weight=\"bold\">{name}</text>" +
        $"<text x=\"12\" y=\"76\" font-family=\"Arial\" font-size=\"12\">{reason}</text>" +
        $"<text x=\"12\" y=\"92\" font-family=\"Arial\" font-size=\"12\">{DateTime.Now:yyyy-MM-dd}</text>" +
        "</svg>";

    byte[] data = Encoding.UTF8.GetBytes(svg);

    using (MemoryStream stream = new MemoryStream(data))
    {
        field.Image = new SignatureImage(stream);
    }
}

private void signWithStampButton_Click(object sender, RoutedEventArgs e)
{
    X509Certificate2 certificate = X509CertificateLoader.LoadPkcs12FromFile(
        "certificate.pfx", "123", X509KeyStorageFlags.Exportable);

    SignatureField field = textControl1.SignatureFields.GetItem("txsign");

    if (field == null)
    {
        MessageBox.Show(this, "The document has no signature field named txsign.");
        return;
    }

    SetSignatureStamp(field);

    SaveSettings saveSettings = new SaveSettings()
    {
        SignatureFields = new DigitalSignature[]
        {
            new DigitalSignature(certificate, "", field.Name)
        }
    };

    textControl1.Save("signed-stamp.pdf", StreamType.AdobePDF, saveSettings);
}
```

The code works as follows:

- The name and the reason come from the field's `SignerData`, which users enter on the ribbon or your code sets as a new `SignerData` object. `SecurityElement.Escape` keeps characters such as `&` and `<` from breaking the SVG.
- The stamp is written into a `MemoryStream`, and the `SignatureImage` constructor reads it from there.
- The date in the stamp comes from the computer. With a time server, the trusted signing time is part of the signature itself.

The blog article [PDF Digital Signatures: Signature Appearance in C#](https://www.textcontrol.com/blog/2023/12/19/pdf-digital-signatures-signature-appearance-in-csharp/) builds a similar stamp around an existing SVG signature and places the field at a corner of the page. Its result in Adobe Acrobat:

![A signed signature field in Adobe Acrobat that shows a handwritten signature next to red text with the signer's name, address and the date.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/signature-custom-appearance.2e5fceba.webp)

### What the PDF Contains

- **A signed field** shows its image. Adobe Acrobat Reader opens its validation status on a click and lists it by field name in the **Signatures** panel.
- **A field without a `DigitalSignature`** stays an unsigned signature field in the PDF, which a PDF reader can sign later, for example Acrobat Reader with a digital ID.
- **A whole-document signature** with `SaveSettings.DigitalSignature` uses an invisible field instead, as [Signing PDF Documents](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/signing/llms-full.txt) describes.

This is the field *txsign* from Getting Started after signing, with the validation status open:

![Adobe Acrobat showing a signed signature field with a handwritten signature and the validation status of the signature of the field txsign.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-wpf/signature-field-validated.b43f5137.webp)

### Next Steps

- [Signature Fields](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/document-editor/signature-fields/llms-full.txt) in Document Editor: let users insert fields and enter signer data.
- [Multiple Signatures](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/llms-full.txt): several signers and certificates in one document.
- [Timestamp Configuration](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/timestamps/llms-full.txt): a trusted timestamp for each field.

---

## Nearby

- **Previous:** [Certificates](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/certificates/llms-full.txt)
- **Next:** [Multiple Signatures](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/digital-signatures/multiple/llms-full.txt)
