Content Controls (Structured Document Tags)

Content Controls (also called Structured Document Tags) allow you to customize a document. GemBox.Document supports two kinds of Content Controls; BlockContentControl is used as a block element and InlineContentControl is used as an inline element.

The ContentControlType enumeration contains a list of Content Control types that are supported through GemBox.Document's API. Each Content Control element can be customized using the ContentControlProperties class.

The following example demonstrates how you can create various Content Controls and change their properties.

Screenshot of Word file with Content Controls
Word document with Content Controls or Structured Document Tags
using GemBox.Document;
using GemBox.Document.CustomMarkups;

class Program
{
    static void Main()
    {
        // If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        var document = new DocumentModel();

        var section = new Section(document);
        document.Sections.Add(section);

        // Create locked Rich Text Content Control.
        var richTextControl = new BlockContentControl(document, ContentControlType.RichText,
            new Paragraph(document, "This text is inside Rich Text Content Control."),
            new Paragraph(document, "It cannot be deleted or edited."));
        richTextControl.Properties.LockEditing = true;
        richTextControl.Properties.LockDeleting = true;
        section.Blocks.Add(richTextControl);

        // Create named Plain Text Content Control.
        var plainTextControl = new BlockContentControl(document, ContentControlType.PlainText,
            new Paragraph(document, "Plain Text Content Control with tag and title."));
        plainTextControl.Properties.Tag = "Plain Text Name";
        plainTextControl.Properties.Title = "Plain Text Title";
        section.Blocks.Add(plainTextControl);

        // Create CheckBox Content Control.
        var checkBoxControl = new InlineContentControl(document, ContentControlType.CheckBox,
           new Run(document, "☒") { CharacterFormat = { FontName = "MS Gothic" } });
        checkBoxControl.Properties.Checked = true;

        // Create ComboBox Content Control.
        var comboBoxControl = new InlineContentControl(document, ContentControlType.ComboBox,
            new Run(document, "<Select GemBox Component>"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("<Select GemBox Component>", "NONE"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("GemBox.Spreadsheet", "GBS"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("GemBox.Document", "GBD"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("GemBox.Pdf", "GBA"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("GemBox.Presentation", "GBP"));
        comboBoxControl.Properties.ListItems.Add(new ContentControlListItem("GemBox.Email", "GBE"));

        section.Blocks.Add(new Paragraph(document,
            checkBoxControl,
            new SpecialCharacter(document, SpecialCharacterType.LineBreak),
            comboBoxControl));

        document.Save("Content Controls.docx");
    }
}
Imports GemBox.Document
Imports GemBox.Document.CustomMarkups

Module Program

    Sub Main()

        ' If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Dim document As New DocumentModel()

        Dim section As New Section(document)
        document.Sections.Add(section)

        ' Create locked Rich Text Content Control.
        Dim richTextControl As New BlockContentControl(document, ContentControlType.RichText,
            New Paragraph(document, "This text is inside Rich Text Content Control."),
            New Paragraph(document, "It cannot be deleted or edited."))
        richTextControl.Properties.LockEditing = True
        richTextControl.Properties.LockDeleting = True
        section.Blocks.Add(richTextControl)

        ' Create named Plain Text Content Control.
        Dim plainTextControl As New BlockContentControl(document, ContentControlType.PlainText,
            New Paragraph(document, "Plain Text Content Control with tag and title."))
        plainTextControl.Properties.Tag = "Plain Text Name"
        plainTextControl.Properties.Title = "Plain Text Title"
        section.Blocks.Add(plainTextControl)

        ' Create CheckBox Content Control.
        Dim checkBoxControl As New InlineContentControl(document, ContentControlType.CheckBox,
           New Run(document, "☒") With {.CharacterFormat = New CharacterFormat() With {.FontName = "MS Gothic"}})
        checkBoxControl.Properties.Checked = True

        ' Create ComboBox Content Control.
        Dim comboBoxControl As New InlineContentControl(document, ContentControlType.ComboBox,
            New Run(document, "<Select GemBox Component>"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("<Select GemBox Component>", "NONE"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("GemBox.Spreadsheet", "GBS"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("GemBox.Document", "GBD"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("GemBox.Pdf", "GBA"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("GemBox.Presentation", "GBP"))
        comboBoxControl.Properties.ListItems.Add(New ContentControlListItem("GemBox.Email", "GBE"))

        section.Blocks.Add(New Paragraph(document,
            checkBoxControl,
            New SpecialCharacter(document, SpecialCharacterType.LineBreak),
            comboBoxControl))

        document.Save("Content Controls.docx")

    End Sub
End Module

Content Controls with XML Mapping

Content Controls can be mapped to XML nodes from DocumentModel.CustomXmlParts.

With GemBox.Document you can update separately the values in mapped XML (CustomXmlPart.Data) and the content of Content Control (BlockContentControl.Blocks or InlineContentControl.Inlines.

The following example demonstrates how you can change XML node in custom XML part and update the content of Content Control based on that mapped XML node.

Screenshot of Word file with changed XML Mapping
Word document with changed XML Mapping
using System.IO;
using System.Xml;
using System.Linq;
using System.Text.RegularExpressions;
using GemBox.Document;
using GemBox.Document.CustomMarkups;

class Program
{
    static void Main()
    {
        // If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        var document = DocumentModel.Load("%#XmlMapping.docx%");

        // Get the Content Control.
        var contentControl = (InlineContentControl)document.GetChildElements(true, ElementType.InlineContentControl).First();
        var xmlMapping = contentControl.Properties.XmlMapping;

        // Get the mapped XML part.
        var xmlPart = xmlMapping.CustomXmlPart;

        // Create XmlDocument from XML.
        var xmlDocument = new XmlDocument();
        xmlDocument.Load(new MemoryStream(xmlPart.Data));

        // Create a namespace manager.
        var namespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);

        // If XmlMapping specifies prefixes, parse them and fill the namespace manager.
        if (!string.IsNullOrEmpty(xmlMapping.PrefixMappings))
        {
            var regex = new Regex("xmlns:(?<prefix>[\\S]+)='(?<namespace>[\\S]+)'");
            foreach (Match match in regex.Matches(xmlMapping.PrefixMappings))
                namespaceManager.AddNamespace(match.Groups["prefix"].Value, match.Groups["namespace"].Value);
        }

        // Locate the node to which is the Content Control mapped using XPath.
        var node = xmlDocument.SelectSingleNode(xmlMapping.XPath, namespaceManager);

        // Change the node value.
        node.InnerText = "%NewFirstName%";

        // Update the XmlPart Data.
        var outputMemoryStream = new MemoryStream();
        xmlDocument.Save(outputMemoryStream);
        xmlPart.Data = outputMemoryStream.ToArray();

        // Get the node value.
        var nodeValue = node.InnerText;

        // Update Content Control inlines.
        contentControl.Inlines.Clear();
        contentControl.Inlines.Add(new Run(document, nodeValue)
        {
            CharacterFormat = contentControl.Properties.CharacterFormat
        });

        document.Save("Xml Mapping.%OutputFileType%");
    }
}
Imports System.IO
Imports System.Xml
Imports System.Linq
Imports System.Text.RegularExpressions
Imports GemBox.Document
Imports GemBox.Document.CustomMarkups

Module Program

    Sub Main()

        ' If using Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Dim document = DocumentModel.Load("%#XmlMapping.docx%")

        ' Get the Content Control.
        Dim contentControl = CType(document.GetChildElements(True, ElementType.InlineContentControl).First(), InlineContentControl)
        Dim xmlMapping = contentControl.Properties.XmlMapping

        ' Get the mapped XML part.
        Dim xmlPart = xmlMapping.CustomXmlPart

        ' Create XmlDocument from XML.
        Dim xmlDocument = new XmlDocument()
        xmlDocument.Load(new MemoryStream(xmlPart.Data))

        ' Create a namespace manager.
        Dim namespaceManager = New XmlNamespaceManager(xmlDocument.NameTable)

        ' If XmlMapping specifies prefixes, parse them and fill the namespace manager.
        If Not String.IsNullOrEmpty(xmlMapping.PrefixMappings) Then
            Dim regex = New Regex("xmlns:(?<prefix>[\\S]+)='(?<namespace>[\\S]+)'")
            For Each match As Match In regex.Matches(xmlMapping.PrefixMappings)
                namespaceManager.AddNamespace(match.Groups("prefix").Value, match.Groups("namespace").Value)
            Next
        End If

        ' Locate the node to which is the Content Control mapped using XPath.
        Dim node = xmlDocument.SelectSingleNode(xmlMapping.XPath, namespaceManager)

        ' Change the node value.
        node.InnerText = "%NewFirstName%"

        ' Update the XmlPart Data.
        Dim outputMemoryStream = new MemoryStream()
        xmlDocument.Save(outputMemoryStream)
        xmlPart.Data = outputMemoryStream.ToArray()

        ' Get the node value.
        Dim nodeValue = node.InnerText

        ' Update Content Control inlines.
        contentControl.Inlines.Clear()
        contentControl.Inlines.Add(New Run(document, nodeValue) With
        {
            .CharacterFormat = contentControl.Properties.CharacterFormat
        })

        document.Save("Xml Mapping.%OutputFileType%")

    End Sub
End Module

Check next example or download examples from GitHub.