TX Text Control .NET for WPF

Document Metadata

Topic

Every PDF carries a small set of facts about itself: a title, an author, a subject, keywords, the application that created it and its dates. PDF readers show them as document properties, Windows Search and document management systems index them, and PDF/UA requires a title. With TX Text Control .NET for WPF, this metadata is part of the document in the TextControl: a loaded document brings it along, code or the user changes it, and the next save writes it. Find out which values a PDF stores, how to change the metadata of an existing PDF, how to read it from many files and how to read the raw metadata.

The document properties of a first PDF are set in Create a PDF in Getting Started, and Loading Documents reads them after loading.

Where Metadata Lives

The metadata of the document in the editor is the DocumentSettings object of the TextControl: Load fills it, code and the sidebar change it, and every Save stores it, so a PDF that is loaded and saved again keeps its metadata. SaveSettings overrides values for a single save, and LoadSettings reports what one Load found. Document Properties describes these properties, the DocumentSettings panel of the WPF Sidebar and how SaveSettings overrides them, for every format.

A PDF stores the title, author, subject, keywords, creating application, creation date and modification date. The modification date has no DocumentSettings property: set it with SaveSettings.LastModificationDate and read it with LoadSettings.LastModificationDate. Save the Document as PDF in Getting Started sets all of them for a first PDF and shows them in the Document Properties dialog of Adobe Acrobat.

The fields of the sidebar panel are listed in Show the Document Settings Panel; its attachments category is described in Attachments.

Update the Metadata of an Existing PDF

Loading a PDF fills DocumentSettings, so changing one value and saving keeps all others. The handlers on this page go into MainWindow.xaml.cs, which needs using System;, using System.Windows; and using TXTextControl;. The following one replaces the keywords of an invoice:

private void updatePdfButton_Click(object sender, RoutedEventArgs e)
{
    textControl1.Load("invoice.pdf", StreamType.AdobePDF);

    // Filled from the loaded PDF
    DocumentSettings documentSettings = textControl1.DocumentSettings;
    MessageBox.Show(this, $"Title: {documentSettings.DocumentTitle}\nCreated with: {documentSettings.CreatorApplication}");

    documentSettings.DocumentKeywords = new string[] { "invoice", "INV-2025-001", "paid" };

    textControl1.Save("invoice-paid.pdf", StreamType.AdobePDF,
        new SaveSettings() { LastModificationDate = DateTime.Now });
}

The saved PDF names the original creating application unless you set a new CreatorApplication. Its pages are rebuilt from the imported content, as PDF Import and Its Limitations describes, so it's a new PDF with the old metadata.

Build a Keyword Index of PDF Files

For many files, a ServerTextControl reads the metadata without touching the editor. It is the TX Text Control without a user interface and is part of the WPF package. The following handler writes the title, author, keywords and creation date of each PDF in Invoices to index.json, with using System.Collections.Generic;, using System.IO;, using System.Linq; and using System.Text.Json;:

private void buildIndexButton_Click(object sender, RoutedEventArgs e)
{
    List<object> index = new List<object>();

    using (ServerTextControl tx = new ServerTextControl())
    {
        // Initialize the new instance before using it
        tx.Create();

        foreach (string file in Directory.GetFiles("Invoices", "*.pdf"))
        {
            // Text only: the metadata doesn't need the layout of the pages
            LoadSettings loadSettings = new LoadSettings()
            {
                PDFImportSettings = PDFImportSettings.GenerateLines
            };

            tx.Load(file, StreamType.AdobePDF, loadSettings);

            index.Add(new
            {
                File = System.IO.Path.GetFileName(file),
                Title = loadSettings.DocumentTitle,
                Author = loadSettings.Author,
                Keywords = (loadSettings.DocumentKeywords ?? Array.Empty<string>()).Select(keyword => keyword.Trim()).ToArray(),
                Created = loadSettings.CreationDate == DateTime.MinValue ? (DateTime?)null : loadSettings.CreationDate
            });
        }
    }

    File.WriteAllText("index.json", JsonSerializer.Serialize(index, new JsonSerializerOptions { WriteIndented = true }));
}

A PDF without keywords returns null for DocumentKeywords, and one without a creation date DateTime.MinValue; the index turns them into an empty array and null. For keywords that help search, the blog article Enhancing PDF Searchability in Large Repositories by Adding and Reading Keywords Using C# .NET suggests consistent tags and 5 to 10 keywords per document.

Store Custom Properties

Data of your own, such as an invoice number, goes into the UserDefinedDocumentProperties of DocumentSettings, as Set the Properties in Code shows. The TX Text Control format, RTF, DOC and DOCX save and load these properties, PDF doesn't, so keep such data in a DOCX version of the document or in an attachment of the PDF.

Give an Accessible PDF Its Title

A PDF without a title fails PDF/UA validation, the check for accessible documents. TX Text Control writes the tagged structure of an accessible PDF since version 34.0, as Create an Accessible PDF (PDF/UA) explains, and takes the title from DocumentSettings.DocumentTitle. The following handler asks the user for a missing title by opening a sidebar named sidebarLeft, declared as in Show the Document Settings Panel, and saves only once there is one:

private void saveAccessiblePdfButton_Click(object sender, RoutedEventArgs e)
{
    if (string.IsNullOrWhiteSpace(textControl1.DocumentSettings.DocumentTitle))
    {
        // Let the user enter the title first
        sidebarLeft.ContentLayout = TXTextControl.WPF.Sidebar.SidebarContentLayout.DocumentSettings;
        sidebarLeft.IsShown = true;
        MessageBox.Show(this, "Enter a title for the document, then save it again.");
        return;
    }

    textControl1.Save("invoice.pdf", StreamType.AdobePDF);
}

A complete check of the title and the descriptive texts of images and tables is built in the blog article Preflighting PDF/UA Documents with TX Text Control in .NET C#.

Read the Raw Metadata of a PDF

LoadEmbeddedData in the PDFImportSettings makes Load return the metadata as stored in the PDF file, through LoadSettings.EmbeddedData. Its keys are EmbeddedDataFormat values, and MetaData is the one for metadata:

private void showRawMetadataButton_Click(object sender, RoutedEventArgs e)
{
    LoadSettings loadSettings = new LoadSettings()
    {
        PDFImportSettings = PDFImportSettings.GenerateTextFrames | PDFImportSettings.LoadEmbeddedData
    };

    textControl1.Load("invoice.pdf", StreamType.AdobePDF, loadSettings);

    if (loadSettings.EmbeddedData != null &&
        loadSettings.EmbeddedData.TryGetValue(EmbeddedDataFormat.MetaData, out object metaData))
    {
        MessageBox.Show(this, metaData.ToString());
    }
}

GenerateTextFrames is the default import, so the editor shows the PDF as usual. EmbeddedData is filled only when LoadEmbeddedData is set, and only with the formats the PDF provides; Text Extraction uses the TextCoordinates entry.

Next Steps

  • Attachments: embed files with metadata of their own.
  • PDF/A: archive documents with their metadata.
  • Document Properties: the document properties of every format and the DocumentSettings panel.
  • Loading Documents: the information LoadSettings returns for any format.