How to Work with Structured Document Tags in .NET
This guide shows how to insert, configure, find, remove, and bind data to structured document tags (content controls) in Aspose.Words FOSS for .NET, using the StructuredDocumentTag class in the Aspose.Words.Markup namespace. It covers which content-control types DocumentBuilder can insert, setting type-specific content such as checkbox state or drop-down choices, locating controls by tag or title, removing a control with or without its contents, and mapping a control to custom XML data.
Step-by-Step Guide
Step 1: Install the Package
Aspose.Words FOSS for .NET does not yet publish a NuGet package – build the library from source instead. Clone https://github.com/aspose-words-foss/Aspose.Words-FOSS-for-.NET.git, then build Aspose.Words.sln in Release configuration with the .NET SDK and reference the resulting Aspose.Words assembly from your project. The library targets .NET Standard 2.0, so it runs on .NET Framework 4.6.2+ and .NET 6/8/10.
Step 2: Import Required Classes
Add a using Aspose.Words; directive for Document and DocumentBuilder, and a using Aspose.Words.Markup; directive for StructuredDocumentTag, SdtType, SdtListItem, SdtListItemCollection, XmlMapping, and the other content-control classes this guide covers.
Step 3: Check Which Content-Control Types You Can Insert
Before inserting, check whether the target SdtType is one of the seven types accepted by DocumentBuilder.InsertStructuredDocumentTag(SdtType): PlainText, RichText, Checkbox, DropDownList, ComboBox, Picture, and Date. RepeatingSection and RepeatingSectionItem cannot be inserted at a text cursor with this method – they wrap entire paragraphs or table rows instead. The remaining SdtType values that can appear in a Word file but are not present in the Word UI as insertable types – None, Bibliography, Citation, Equation, BuildingBlockGallery, DocPartObj, Group, and EntityPicker – are not accepted by this insertion method at all.
Step 4: Insert a Content Control at the Cursor
Call DocumentBuilder.InsertStructuredDocumentTag(SdtType) with one of the seven supported types to insert a new control at the builder’s current cursor position; the call returns the new StructuredDocumentTag. Set Tag and Title on the returned control to give it the identifying strings authors see in Word, and set PlaceholderName (backed by a Placeholder BuildingBlock) for the prompt text Word shows while the control is empty – IsShowingPlaceholderText reports whether that prompt is currently displayed.
Step 5: Configure Type-Specific Content
For a checkbox control, read or set StructuredDocumentTag.Checked, and call SetCheckedSymbol() / SetUncheckedSymbol() to customize the glyphs shown for each state. For a date control, set FullDate, with DateDisplayFormat and DateDisplayLocale controlling how it renders, DateStorageFormat (SdtDateStorageFormat) controlling how it is stored when bound to XML data, and CalendarType (SdtCalendarType) selecting the calendar system. For a drop-down list or combo box, populate ListItems – an SdtListItemCollection of SdtListItem (DisplayText, Value) – before setting SelectedValue to pick the active choice. For a plain-text control, Multiline is a bool property on StructuredDocumentTag that can be set to configure the control.
Step 6: Control Appearance and Locking
Set Appearance (SdtAppearance) to control how the control is visually delimited in Word, and Color to set its highlight color. ContentsFont and EndCharacterFont control the font applied to the control’s contents and its trailing end character. LockContentControl and LockContents are independent switches – set LockContentControl to block deletion of the control itself, and LockContents to block editing of what is inside it, without affecting the other.
Step 7: Find and Remove Content Controls
Read Range.StructuredDocumentTags – a StructuredDocumentTagCollection scoped to that range – and call GetById(), GetByTag(), or GetByTitle() to locate a specific control, or Remove() / RemoveAt() on the collection to remove one by reference or index. On an individual control, call Remove() to delete the control together with its contents, RemoveSelfOnly() to delete only the wrapper while keeping its contents in the document, or Clear() to empty its contents while keeping the control itself in place.
Step 8: Bind a Control to Custom XML Data
Read StructuredDocumentTag.XmlMapping – an XmlMapping instance – and call SetMapping(customXmlPart, xPath, prefixMapping) to bind the control to an existing custom XML part already present in the document’s custom XML data store, using an XPath expression to select the bound element. XmlMapping.IsMapped reports whether a binding is currently active, CustomXmlPart and StoreItemId identify the bound data part, and Delete() removes the mapping.
Step 9: Handle Content Controls That Span Multiple Sections
A content control spanning more than one document section – reported by IsMultiSection – is represented not by a single StructuredDocumentTag node but by a StructuredDocumentTagRangeStart / StructuredDocumentTagRangeEnd pair, connected through StructuredDocumentTagRangeStart.RangeEnd. Program against the shared IStructuredDocumentTag interface (Tag, Title, Placeholder, PlaceholderName, Appearance, IsShowingPlaceholderText, RemoveSelfOnly()) when code needs to handle both the single-node and ranged forms uniformly, rather than branching on the concrete type.
Common Issues and Fixes
InsertStructuredDocumentTag throws NotImplementedException
The requested SdtType – for example Citation, Equation, or BuildingBlockGallery – is not one of the seven insertable types. Use PlainText, RichText, Checkbox, DropDownList, ComboBox, Picture, or Date instead.
InsertStructuredDocumentTag throws InvalidOperationException
RepeatingSection or RepeatingSectionItem was requested at a text cursor. These two types wrap entire paragraphs or table rows rather than being inserted at a cursor position.
Removing a content control also deletes the text inside it
Remove() deletes the control and its contents together. Call RemoveSelfOnly() instead to keep the contents in the document and drop only the wrapper.
Checkbox doesn’t show the expected symbol
Custom checked and unchecked glyphs were never set. Call SetCheckedSymbol() and SetUncheckedSymbol() on the control.
A drop-down list or combo box shows no choices
ListItems was never populated. Add SdtListItem entries to the control’s ListItems collection before expecting choices to appear, then set SelectedValue to pick the active one.
Frequently Asked Questions
Which content-control types can I insert directly with DocumentBuilder?
PlainText, RichText, Checkbox, DropDownList, ComboBox, Picture, and Date. Other SdtType values are not supported by InsertStructuredDocumentTag().
How do I find all content controls with a specific tag?
Read Range.StructuredDocumentTags and call GetByTag(), or GetByTitle() / GetById() if matching on those identifiers instead.
How do I remove a content control but keep its content in the document?
Call StructuredDocumentTag.RemoveSelfOnly() rather than Remove().
How do I bind a content control to custom XML data?
Call XmlMapping.SetMapping() on the control’s XmlMapping, pointing it at an existing custom XML part and an XPath expression within it.
How is a content control that spans multiple sections different from an ordinary one?
It is represented as a StructuredDocumentTagRangeStart / StructuredDocumentTagRangeEnd pair instead of a single StructuredDocumentTag node; both forms implement IStructuredDocumentTag, so IsMultiSection tells you which form you’re working with.