Docotic.Pdf 10 migration guide
This guide describes the breaking changes introduced in Docotic.Pdf 10.0 and provides examples showing how to implement previous behavior using the updated API.
The guide also lists obsolete properties and methods and describes the recommended migration paths.

If anything in this guide is unclear, you need additional examples, or you encounter a migration scenario not covered here, please contact us.
Why the changes?
Evolving over the years, the Docotic.Pdf API grew into a very large one. But some of the conceptually similar features were implemented differently. There were cases of design decisions that can be improved. Some data structures promised too much and/or didn't map cleanly to PDF structures.
In the version 10.0 we decided to improve in all these areas.
What have changed?
Most changes in Docotic.Pdf 10 affect collections and the APIs that expose them.
Docotic.Pdf collections no longer implement ICollection<T> or ICollection. Several new
collection types have been introduced, and some existing collections have been marked obsolete.
Classes that expose collections still provide access to their items, but the available methods and properties have changed.
Collections and object identity
API members that previously returned PdfCollection<T>, PdfList<T>, or types derived from them
now return IEnumerable<T> or other types that implement IEnumerable<T>.
In some cases, the original members are marked obsolete and replaced with new members that return
IEnumerable<T> or a type that implements this interface.
When a return type changes from PdfCollection<T> to IEnumerable<T>, collection-specific members
such as Count, the indexer, and GetAt(int) are no longer available. Use LINQ methods to perform
the corresponding operations:
PdfCollection<T>.Count->IEnumerable<T>.Count()PdfCollection<T>.this[int]->IEnumerable<T>.ElementAt(int)orIEnumerable<T>.ToArray()[int]
The Count() and ElementAt(int) methods enumerate the sequence to obtain the requested
information. If you need to access multiple elements by index, consider materializing the sequence
into an array first.
On runtimes earlier than .NET 9, using ToList() instead of ToArray() may result in lower memory
consumption.
Changes from PdfList<T> or a type derived from it to a type implementing IEnumerable<T>
preserve the Count and indexing members, as well as methods for adding and removing items.
In all cases, the GetAt(int) method is removed. Use the indexer instead.
Object identity changes
Collections now create high-level objects from the underlying PDF structures each time an item is accessed or a collection is enumerated. In previous versions, these objects were cached.
As a result, accessing the same collection item multiple times does not guarantee that the same object instance is returned. Avoid relying on reference equality or object identity when working with objects obtained from collections.
This change also affects collection operations that rely on object comparison. The Contains(T)
and IndexOf(T) methods are no longer available. For list-based collections, the Remove(T)
method is also no longer available.
Update code that uses these methods to rely on positional logic instead.
Replaced and obsolete members
Previous versions of Docotic.Pdf exposed collections through members typed as
ReadOnlyCollection<T>, PdfCollection<T>, or ICollection<T>. In version 10, many of these
members are obsolete, while others have been replaced with new members that use more appropriate
types.
Depending on the scenario, the new members return T[], IEnumerable<T>, or a specialized
collection type. Review the migration instructions to identify the appropriate replacements.
Improved APIs
Docotic.Pdf 10 also introduces improved APIs for:
- pages collection
- PDF outlines (bookmarks)
- layers (optional content groups)
- choice fields (combo boxes and list boxes)
- ink annotations
- XMP metadata
- page labels
API changes by class
This section describes API changes in Docotic.Pdf 10, organized by class name in alphabetical order. Each subsection outlines changes to methods and properties and provides guidance on how to update your code to migrate to the new version.
Pdf3dStream
The Views property is now of type Pdf3dViewCollection instead of PdfList<Pdf3dView?>.
See Collections and object identity for migration guidance.
PdfAction
The behavior of PdfActionCollection, the return type of the NextActions property, has changed.
PdfActionCollection
PdfActionCollection was refactored from a concrete list into a lightweight enumerable and no
longer derives from PdfList<PdfAction?>.
See Collections and object identity for migration guidance.
PdfArtifact
The return type of GetAttachmentEdges() is now string[]? instead of string[].
The method now returns null when no attachment edges are specified in the underlying PDF
structure. In previous versions, it returned an empty array in such cases.
PdfCanvas
The GetTextData() method now returns IEnumerable<PdfTextData> instead of
PdfCollection<PdfTextData>.
See Collections and object identity for migration guidance.
PdfClipRegion
The PdfCollection<PdfPath> IntersectedPaths property is now obsolete. Use the new
IEnumerable<PdfPath> GetIntersectedPaths() method instead.
See Collections and object identity for migration guidance.
PdfComboBox
The following members have changed:
AddItemandAddItemsmethods (see AddItem and AddItems methods).ClearItemsmethod (see ClearItems method).Itemsproperty (see Items property).
PdfDeviceNColorSpace
The ReadOnlyCollection<string> Names property is now obsolete. Use the new string[] GetNames()
method instead.
PdfDocument
PdfDocument serves as the central entry point for working with many different aspects of a PDF
file. The class is affected by several migration-related changes, including updates to the
collection implementation and revisions to the APIs for bookmarks and layers.
The following members are affected:
- AddPage method
- AssociatedFiles property
- CopyPages methods
- CreateLayer methods
- ExtractPages methods
- GetPage method
- IndexOf method
- Insert method
- Layers property
- MovePage method
- MovePages methods
- OpenImage methods
- OutlineRoot property
- PageCount property
- PageLabels property
- Pages property
- RemovePage methods
- RemovePages methods
- RemoveUnusedFontGlyphs methods
- RemoveWidget method
- SharedAttachments property
- SharedScripts property
- SharedViews property
- SwapPages method
PdfDocument.AddPage method
The AddPage() method is now obsolete. Use the Pages collection and its Add() method instead.
PdfDocument.AssociatedFiles property
The AssociatedFiles property is now of type PdfFileSpecificationCollection instead of
PdfList<PdfFileSpecification?>.
See Collections and object identity for migration guidance.
PdfDocument.CopyPages methods
All CopyPages methods are now obsolete. Use the corrseponding methods from the Pages
collection instead:
CopyPages(int, int)->Pages.CopyRange(int, int)CopyPages(int, int, PdfConfigurationOptions)->Pages.CopyRange(int, int, PdfConfigurationOptions)CopyPages(int[])->Pages.Copy(int[])
The CopyPages(PdfPage[]) method has no direct replacement. Update any code that identifies pages
by object reference to use page positions in the collection instead.
PdfDocument.CreateLayer methods
The CreateLayer methods are obsolete. Use OptionalContent.Layers.Add to create a layer and add
it to the document's layer collection. Access the collection through the OptionalContent
property.
Replace the obsolete methods as follows:
CreateLayer(string)-> useOptionalContent.Layers.Add(string)CreateLayer(string, bool, params PdfLayerIntent[])-> useOptionalContent.Layers.Add(string, bool, params string[])
The replacement for the second overload accepts intent names as strings rather than
PdfLayerIntent values. See PdfLayerIntent for details about migrating layer
intents.
PdfDocument.ExtractPages methods
All ExtractPages methods are now obsolete. Use the corrseponding methods from the Pages
collection instead:
ExtractPages(int, int)->Pages.ExtractRange(int, int)ExtractPages(int, int, PdfConfigurationOptions)->Pages.ExtractRange(int, int, PdfConfigurationOptions)ExtractPages(int[])->Pages.Extract(int[])
The ExtractPages(PdfPage[]) method has no direct replacement. Update any code that identifies
pages by object reference to use page positions in the collection instead.
PdfDocument.GetPage method
The GetPage(int) method is now obsolete. Use the Pages collection and its indexer instead.
PdfDocument.IndexOf method
The IndexOf(PdfPage) method is now obsolete. Use the Pages collection and positional access
instead.
PdfDocument.Insert method
The Insert(int) method is now obsolete. Use the Pages collection and its Insert(int) method
instead.
PdfDocument.Layers property
The Layers property is now obsolete. Use OptionalContent.Layers to access the document's layer
collection. This changes the collection type from PdfCollection<PdfLayer?> to
PdfLayerCollection, which implements IEnumerable<PdfLayer?>.
See Collections and object identity for migration guidance.
PdfDocument.MovePage method
The MovePage(int, int) method is now obsolete. Use the Pages collection and its Move(int,
int) method instead.
PdfDocument.MovePages methods
All MovePages methods are now obsolete. Use the corrseponding methods from the Pages collection
instead:
MovePages(int, int, int)->Pages.MoveRange(int, int, int)MovePages(int[], int)->Pages.Move(int[], int)
PdfDocument.OpenImage methods
The OpenImage methods themselves have not changed. However, there are behavioral changes in
PdfImageFrames, the type returned by these methods.
PdfDocument.OutlineRoot property
The PdfOutlineItem OutlineRoot property is now obsolete and has been replaced by the
PdfOutlineItemCollection Outlines property instead.
This change clarifies the difference between collection of outline items and an individual outline
item. The API of PdfOutlineItemCollection more accurately reflects the underlying PDF structure
and exposes only operations that are meaningful and efficient for a bookmark collection.
Behavioral changes
With OutlineRoot, the root outline item acted as a synthetic container:
OutlineRoot.Parentwas alwaysnull.- Items in
OutlineRoot.ChildrenhadOutlineRootas their parent. WithOutlines, there is no synthetic root item. All top-level bookmarks havenullas their parent.
Members without replacements
The following PdfOutlineItem members do not apply to a bookmark collection and therefore have no
equivalent in PdfOutlineItemCollection:
ParentPagePageIndexTitleActionOpenColorBoldItalic
Member mapping
The OutlineRoot.Children is now represented by Outlines itself. Here's how to enumerate
top-level bookmarks:
// Before v10
foreach (var item in pdf.OutlineRoot.Children)
Console.WriteLine(item.Title);
// v10 and later
foreach (var item in pdf.Outlines)
Console.WriteLine(item.Title);
There is no direct replacement for OutlineRoot.ChildCount, but you can use LINQ instead:
Outlines.Count().
OutlineRoot.RemoveAllChildren() maps to Outlines.Clear(), and
OutlineRoot.RemoveChild(PdfOutlineItem) maps to Outlines.Remove(PdfOutlineItem).
The Outlines collection does not support index-based operations. For the reasons behind this
change and migration alternatives, see the PdfOutlineItem.Children
section.
Adding and inserting bookmarks
The PdfOutlineItemCollection.Add(string) method replaces all OutlineRoot.AddChild methods.
Create a new bookmark with the desired title, then configure the returned PdfOutlineItem by
setting its action, color, destination, and other properties as needed.
To replace the OutlineRoot.InsertChild methods, use
PdfOutlineItemCollection.InsertBefore(PdfOutlineItem, string) or
PdfOutlineItemCollection.InsertAfter(PdfOutlineItem, string). The approach is similar to Add:
insert the new bookmark first, then configure the returned item.
One important difference is that the new API uses a reference item rather than an index. Instead of specifying the position of an existing bookmark, you specify the bookmark before or after which the new bookmark should be inserted.
PdfDocument.PageCount property
The PageCount property is now obsolete. Use the Pages collection and its Count property
instead.
PdfDocument.PageLabels property
The PageLabels property is now of type PdfPageLabelMap instead of PdfPageLabels. This better
reflects how page labels are stored internally in a PDF document. The new type exposes a similar
set of methods and properties, but some members behave differently.
Member mapping
The following table shows how members of PdfPageLabels map to members of PdfPageLabelMap:
Mapping of old members to new ones:
PdfPageLabels PageLabels->PdfPageLabelMap PageLabelsPdfPageLabels.AddRangeoverloads ->PdfPageLabelMap.Add, except for overloads that accept alastPageparameter, which have no direct replacementPdfPageLabels.Count-> use LINQ if needed:PageLabels.Count()
The following PdfPageLabels members are no longer supported:
Contains(PdfPageLabelingRange),IndexOf(PdfPageLabelingRange), andRemove(PdfPageLabelingRange). See Object identity-based operations.GetAt(int)andRemoveAt(int). See Index-based operations.
The enumerator type of the PageLabels collection has changed from
IEnumerator<PdfPageLabelingRange> GetEnumerator()
to
IEnumerator<PdfPageLabelEntry> GetEnumerator()
This allows you to iterate over entries that pair the zero-based index of the first page in a labeling range with the labeling characteristics for that range.
Object identity-based operations
The PageLabels collection creates a new PdfPageLabelEntry instance, containing a new
PdfPageLabel instance, each time the indexer is accessed or the collection is enumerated. Because
each lookup returns different object instances, operations that depend on value or reference
equality are no longer supported.
Update any code that uses Contains(PdfPageLabelingRange), IndexOf(PdfPageLabelingRange), or
Remove(PdfPageLabelingRange) to use the indexer and/or enumeration instead.
Index-based operations
PdfPageLabelMap does not provide index-based operations. The indexer and methods that accept
int parameters no longer treat those integers as positions within the collection.
For example, the indexer PageLabels[int] retains the same signature, but its semantics have
changed. Previously, the parameter represented the position of a page-labeling range within the
collection. Now, the parameter represents the index of the first page in a page-labeling range. The
page index acts as a key, and the collection returns the corresponding labeling range.
There is no direct replacement for the PdfPageLabels.RemoveAt(int) method. Instead, enumerate the
map, locate the entry at the desired position, retrieve its first-page index, and remove the
corresponding labeling range by calling PdfPageLabelMap.Remove(int):
PdfPageLabelMap map = pdf.PageLabels;
var entry = map.ElementAt(index);
map.Remove(entry.FirstPageIndex);
AddRange methods
All PdfPageLabels.AddRange methods have been replaced by PdfPageLabelMap.Add methods. However,
there is no direct replacement for AddRange overloads that accept a lastPage parameter.
These overloads allowed you to specify only ranges with non-default labels explicitly. Any ranges that used the default page labels (decimal Arabic numbers matching page indices) were added implicitly.
For example, in a 10-page document, the following code creates three labeling ranges:
- lowercase Roman numerals for page indices
0..3 - an implicitly added range with decimal Arabic numbering for page indices
4..6 - decimal Arabic numbering with an "A-" prefix starting at page index
7
// Before v10
pdf.PageLabels.AddRange(7, PdfPageNumberingStyle.DecimalArabic, "A-", 8);
pdf.PageLabels.AddRange(0, 3, PdfPageNumberingStyle.LowercaseRoman);
Unlike PdfPageLabels, PdfPageLabelMap never adds labeling ranges implicitly. You must
explicitly add every range. The preceding example becomes:
// v10 and later
pdf.PageLabels.Add(7, PdfPageNumberingStyle.DecimalArabic, "A-", 8);
pdf.PageLabels.Add(0, PdfPageNumberingStyle.LowercaseRoman);
pdf.PageLabels.Add(4, PdfPageNumberingStyle.DecimalArabic);
PdfPageLabels also implicitly added a labeling range starting at page index 0 if no such range
had been added explicitly. PdfPageLabelMap does not do this. When configuring page labels, ensure
that the collection either:
- contains no labeling ranges, or
- contains a labeling range that starts at page index
0.
PdfDocument.Pages property
The Pages property is now of type PdfPageCollection instead of a PdfCollection<PdfPage>.
See Collections and object identity for migration guidance.
The sequence returned by the enumerator of the new collection may include null entries when a
page cannot be constructed from the underlying PDF data. In earlier versions, such pages appeared
as empty PdfPage instances.
In version 10, the new PdfPageCollection type also replaces several page-related members
previously exposed directly on PdfDocument. These members now reside on the Pages collection.
Mapping of old page-related members to new ones:
AddPage()->Pages.Add()CopyPages(PdfPage[])-> not supported; use positional logic insteadCopyPages(int, int)->Pages.CopyRange(int, int)CopyPages(int, int, PdfConfigurationOptions)->Pages.CopyRange(int, int, PdfConfigurationOptions)CopyPages(int[])->Pages.Copy(int[])ExtractPages(PdfPage[])-> not supported; use positional logic insteadExtractPages(int, int)->Pages.ExtractRange(int, int)ExtractPages(int, int, PdfConfigurationOptions)->Pages.ExtractRange(int, int, PdfConfigurationOptions)ExtractPages(int[])->Pages.Extract(int[])GetPage(int)->Pages[int]IndexOf(PdfPage)-> not supported; use positional logic insteadInsertPage(int)->Pages.Insert(int)MovePage(int, int)->Pages.Move(int, int)MovePages(int, int, int)->Pages.MoveRange(int, int, int)MovePages(int[], int)->Pages.Move(int[], int)PageCount->Pages.CountRemovePage(PdfPage)-> not supported; use positional logic insteadRemovePage(int)->Pages.RemoveAt(int)RemovePages(PdfPage[])-> not supported; use positional logic insteadRemovePages(int)->Pages.RemoveFrom(int)RemovePages(int, int)->Pages.RemoveRange(int, int)RemovePages(int[])->Pages.RemoveAt(int[])SwapPages(int, int)->Pages.Swap(int, int)
PdfDocument.RemovePage methods
The RemovePage(int) method is now obsolete. Use the Pages collection and its RemoveAt(int)
method instead.
The RemovePage(PdfPage) method is also obsolete. There is no direct replacement for this
overload. Update any code that identifies pages by object reference to use page positions in the
collection instead.
PdfDocument.RemovePages methods
All RemovePages methods are now obsolete. Use the corrseponding methods from the Pages
collection instead:
RemovePages(int)->Pages.RemoveFrom(int)RemovePages(int, int)->Pages.RemoveRange(int, int)RemovePages(int[])->Pages.RemoveAt(int[])
The RemovePages(PdfPage[]) method has no direct replacement. Update any code that identifies
pages by object reference to use page positions in the collection instead.
PdfDocument.RemoveUnusedFontGlyphs methods
All RemoveUnusedFontGlyphs overloads now return PdfFont[] instead of PdfCollection<PdfFont>.
The following table shows how to migrate code that uses the returned collection:
PdfCollection<PdfFont>.Count->fonts.LengthPdfCollection<PdfFont>.GetAt(int)-> array indexer (fonts[index])PdfCollection<PdfFont>.Contains(PdfFont)->Array.Exists(fonts, f => f == fontToFind)PdfCollection<PdfFont>.IndexOf(PdfFont)->Array.IndexOf(fonts, fontToFind)
Note that each call to a RemoveUnusedFontGlyphs method may create new PdfFont instances.
Therefore, the returned array can contain new PdfFont instances instead of the instances
referenced before the call, even when they refer to the same font.
PdfDocument.RemoveWidget method
The RemoveWidget(PdfWidget) method is now obsolete. Use the PdfWidget.Remove method instead.
Alternatively, if the widget belongs to a page, find it in the page's PdfPage.Widgets collection
and remove it by calling the RemoveAt(int) method.
PdfDocument.SharedAttachments property
The SharedAttachments property is now of type PdfFileSpecificationMap instead of
PdfFileSpecificationCollection. This better reflect the way the collection internally stored in
PDF. The new type exposes a similar set of methods and properties, but several members now behave
differently.
Mapping of old members to new ones:
PdfFileSpecificationCollection SharedAttachments->PdfFileSpecificationMap SharedAttachmentsGet(string)-> removed; use indexer access insteadAdd(PdfFileSpecification)->Add(string, PdfFileSpecification); see note belowRemove(PdfFileSpecification)-> not supported; see note below
The enumerator type for the SharedAttachments collection changed from
IEnumerator<PdfFileSpecification> GetEnumerator() to IEnumerator<PdfFileSpecificationEntry>
GetEnumerator(), allowing iteration over key/value pairs rather than values only.
The indexer SharedAttachments[string] keeps the same signature, but its operational semantics
have changed. Previously, it searched the entire collection for an item whose
PdfFileSpecification.Specification matched the provided string. Now it performs a direct lookup
by key in the underlying PDF structure. It does not parse values to locate a matching pair. Because
of this change, existing code may no longer obtain the expected value from the indexer if the key
and the entry's PdfFileSpecification.Specification do not match.
The SharedAttachments.Add method now requires you to provide the key explicitly. Previously, the
key was derived from the provided value's PdfFileSpecification.Specification, with the -1
suffix appended repeatedly whenever that key was already in use.
The SharedAttachments.Add method also overwrites any existing entry with the same key. Use
SharedAttachments.Contains(string) to check whether a key already exists.
The SharedAttachments collection creates a new PdfFileSpecificationEntry with a new
PdfFileSpecification instance each time an indexer is accessed or the collection is iterated.
Because of this behavior, operations that rely on value comparison are no longer supported. Update
any code that uses Remove(PdfFileSpecification) to rely on positional logic instead.
PdfDocument.SharedScripts property
The SharedScripts property is now of type PdfJavaScriptActionMap instead of
PdfJavaScriptCollection. This change better reflects how document-level JavaScript actions are
stored in PDF documents.
The new type provides similar functionality but no longer exposes index-based operations.
Member mapping
The following table shows how members of PdfJavaScriptCollection map to members of
PdfJavaScriptActionMap:
PdfJavaScriptCollection SharedScripts->PdfJavaScriptActionMap SharedScriptsAdd(PdfJavaScriptAction)->Add(string, PdfJavaScriptAction); see Add methodCount-> use LINQ if needed:Count()Get(string)-> use the indexer instead:this[string]
The following PdfJavaScriptCollection members are no longer supported:
Contains(PdfJavaScriptAction),IndexOf(PdfJavaScriptAction), andRemove(PdfJavaScriptAction). See Object identity-based operations.GetAt(int)andRemoveAt(int). See Index-based operations.
The enumerator type for the SharedScripts collection changed from
IEnumerator<PdfJavaScriptAction> GetEnumerator()
to
IEnumerator<PdfJavaScriptActionEntry> GetEnumerator()
This change allows enumeration of entries that associate script names with JavaScript actions.
Object identity-based operations
PdfJavaScriptActionMap creates a new PdfJavaScriptActionEntry and a new PdfJavaScriptAction
instance each time an entry is retrieved through the indexer or during enumeration. Because of this
behavior, operations that depend on object identity or instance equality are no longer supported.
Update any code that uses Contains(PdfJavaScriptAction), IndexOf(PdfJavaScriptAction), or
Remove(PdfJavaScriptAction) to use action names, the indexer, and/or enumeration instead.
Index-based operations
PdfJavaScriptActionMap does not provide index-based operations. The recommended approach is to
enumerate the collection rather than rely on positional access.
If indexed access is required during migration, you can achieve equivalent behavior using LINQ:
var action = SharedScripts.ElementAt(index).Action;
For scenarios that require multiple indexed lookups, consider materializing the collection first:
var entries = SharedScripts.ToArray();
var action = entries[index].Action;
There is no direct replacement for PdfJavaScriptCollection.RemoveAt(int). Instead, enumerate the
map, locate the entry at the desired position, obtain its name, and remove the corresponding action
using PdfJavaScriptActionMap.Remove(string):
PdfJavaScriptActionMap map = pdf.SharedScripts;
var entry = map.ElementAt(index);
map.Remove(entry.Name);
Add method
The PdfJavaScriptActionMap.Add method requires an explicit action name. Previously,
PdfJavaScriptCollection.Add generated names automatically using the format JSn, where n
started at 0 and increased for each added action.
You can use any string as the name. The name has no predefined semantic meaning; it is used only to identify and organize actions within the underlying PDF structure.
PdfDocument.SharedViews property
The SharedViews property now returns a PdfDocumentViewMap instead of a
PdfDocumentViewCollection.
The new type provides similar functionality but exposes its items as PdfDocumentViewEntry
instances rather than KeyValuePair<string, PdfDocumentView> values.
Member mapping
The following table shows how members of PdfDocumentViewCollection map to members of
PdfDocumentViewMap:
PdfDocumentViewCollection SharedViews->PdfDocumentViewMap SharedViewsGet(string)-> use the indexer instead:this[string]
The enumerator type for the SharedViews collection changed from
IEnumerator<KeyValuePair<string, PdfDocumentView>> GetEnumerator()
to
IEnumerator<PdfDocumentViewEntry> GetEnumerator()
Add method
The behavior of the Add method has changed.
PdfDocumentViewMap.Add replaces any existing entry with the same name. Previously,
PdfDocumentViewCollection.Add threw an ArgumentException if an entry with the specified name
already existed.
If you need to preserve the previous behavior, use the Contains method to check whether an entry
with the specified name already exists before calling Add.
if (pdf.SharedViews.Contains(name))
throw new ArgumentException();
pdf.SharedViews.Add(name, view);
PdfDocument.SwapPages method
The SwapPages(int, int) method is now obsolete. Use the Pages collection and its Swap(int,
int) method instead.
PdfExponentialFunction
The PdfCollection<double> C0 and PdfCollection<double> C1 properties are now obsolete. Use the
double[]? GetC0() and double[]? GetC1() methods instead. These methods returns null when the
corresponding value is not explicitly specified in the PDF. In that case, use the default value
described in the documentation.
The PdfCollection<double> Domain property is now obsolete. Use the double[] GetDomain() method
instead.
The PdfCollection<double>? Range property is now obsolete. Use the double[]? GetRange() method
instead.
PdfFileSpecificationCollection
The collection now implements IEnumerable<PdfFileSpecification?> instead of
IEnumerable<PdfFileSpecification>. This allows the collection to be enumerated without exceptions
even when some items cannot be created from their underlying PDF structures.
The collection introduces new members: Count, this[int], and RemoveAt(int), which enable
positional operations.
The string indexer this[string] has been removed. Use the Get(string) method instead.
The collection may create a new PdfFileSpecification instance each time an index is accessed or
Get(string) is called. Because of this behavior, operations that rely on value comparison are
intentionally not supported. Update any code that uses Remove(PdfFileSpecification) to rely on
positional logic instead.
PdfHideAction
The class no longer inherits collection-related members from PdfControlAction. Instead, it now
derives directly from PdfAction and exposes its widget collection through the
PdfActionWidgetCollection Widgets property. In addition, you can now associate widgets with the
action, not only controls.
Mapping of old members to new ones:
PdfCollection<PdfControl> Controlsis nowPdfActionWidgetCollection WidgetsControlCountwas removed. Use theCountproperty of theWidgetscollection.GetControl(int)was removed. Use the indexer of theWidgetscollection.AddControl(PdfControl)was removed. UseWidgets.Add(PdfWidget).GetAt(int)was removed. Use indexer access instead.
The Widgets collection may construct a new PdfWidget instance each time an index is accessed.
Because of this, operations that rely on value comparison are not supported. Update any code that
uses Contains or IndexOf to rely on positional logic instead.
PdfImageFrames
PdfImageFrames now implements IEnumerable<PdfImageFrame> instead of
PdfCollection<PdfImageFrame>. It still provides a Count property and an indexer.
See Collections and object identity for migration guidance.
PdfInkAnnotation
The PdfInkAnnotation class originally provided methods and properties for reading and updating
the paths of an ink annotation. However, it did not support the modern path-construction model
introduced in PDF 2.0.
Version 10 adds support for this newer model and updates the existing API so the class can work with both the earlier and PDF 2.0 approaches.
To define an ink annotation's path, use either the PdfInkAnnotation.InkList or
PdfInkAnnotation.Path properties. Both expose a PdfInkPathSegmentCollection, but the meaning of
the collection's items differs between the two models. See the documentation for each property for
details about how its collection items are interpreted.
The PathCount property and the GetPath, AddPath, and RemovePathAt methods are now obsolete.
Use the InkList collection and its corresponding methods and properties instead.
Mapping of old members to new ones:
PathCount-> useInkList.CountGetPath(int)-> use theInkListindexer (InkList[int])AddPath(IEnumerable<PdfPoint>)-> useInkList.Add(PdfPoint[])RemovePathAt(int)-> useInkList.RemoveAt(int)
PdfLayer
The PdfLayerIntent[] GetIntents() method is now obsolete. Use string[]? GetIntentNames()
instead.
Unlike GetIntents(), the new method returns null when the corresponding value is not explicitly
specified in the PDF. In this case, use the default value described in the documentation.
In addition to typical intent names, the new method can also return custom, developer-specific intent names.
PdfLayerIntent
The PdfLayerIntent type is now obsolete. Layer intents are now represented by intent names
(string[]), and all methods and properties that use PdfLayerIntent should no longer be used.
Replace PdfLayerIntent values with their corresponding intent names. You can obtain the name of
an existing value by calling ToString().
PdfListBox
The following members have changed:
AddItemandAddItemsmethods (see AddItem and AddItems methods).ClearItemsmethod (see ClearItems method).Itemsproperty (see Items property).
Additionally, the PdfCollection<PdfListItem> SelectedItems property is now obsolete. Use the
IEnumerable<PdfListItem> GetSelectedItems() method instead.
PdfMarkedContent
The GetObjects() method now returns IEnumerable<PdfPageObject> instead of
PdfCollection<PdfPageObject>.
See Collections and object identity for migration guidance.
PdfOutlineItem
The PdfOutlineItem API has been revised to simplify access to child bookmarks and improve
collection handling. Operations on an outline item are now more clearly separated from operations
on its child bookmark collection.
The following members are affected:
- Action property
- AddChild methods
- ChildCount property
- Children property
- GetChild method
- IndexOfChild methods
- InsertChild methods
- Page property
- PageIndex property
- Parent property
- RemoveAllChildren method
- RemoveChild method
- RemoveChildAt method
PdfOutlineItem.Action property
Version 10 refines the role of Action and introduces the new View property. Action now
exposes only explicit PDF actions, while View provides access to document view destinations.
Changes when reading PDFs
In versions prior to 10, when an outline item specified a document view, the Action property
returned a synthesized PdfGoToAction representing that view.
Starting with version 10, Action returns only actions that are explicitly defined in the PDF. If
an outline item specifies a document view instead of an action, Action returns null.
Use the new View property to access the document view associated with an outline item.
Changes when writing PDFs
In previous versions, assigning a PdfGoToAction to Action caused Docotic.Pdf to save the
destination as a document view (PdfDocumentView) rather than as a Go-To action. This optimization
reduced the PDF size while preserving the same behavior: activating the outline item navigated to a
location within the current document.
Starting with version 10, Docotic.Pdf no longer performs this conversion. The value assigned to
Action is now written to the PDF unchanged.
Replacing PdfGoToAction with View
If an outline item should navigate to a location within the same document, use the new View
property instead of assigning a PdfGoToAction to Action. This produces the same compact PDF
representation as in previous versions.
In the examples below, pdf is a PdfDocument and item is a PdfOutlineItem.
// Before v10
item.Action = pdf.CreateGoToPageAction(pageIndex, 0);
// v10 and later
item.View = pdf.CreateView(pageIndex);
PdfOutlineItem.AddChild methods
All AddChild methods are now obsolete. To add child outline items, use the Children collection
and call the PdfOutlineItemCollection.Add method instead.
A single Add method replaces all obsolete AddChild overloads. It accepts only the title of the
outline item to create and returns the newly created PdfOutlineItem. You can then configure
additional properties, such as the action or destination view, on the returned instance.
The following example shows how to replace the overload that accepts a PdfAction:
// Before v10
var child = outlineItem.AddChild(title, action);
// v10 and later
var child = outlineItem.Children.Add(title);
child.Action = action;
The following example shows how to replace the overload that accepts a PdfDocumentView:
// Before v10
var child = outlineItem.AddChild(title, view);
// v10 and later
var child = outlineItem.Children.Add(title);
child.View = view;
The following example shows how to replace the overload that accepts a PdfPage:
// Before v10
var child = outlineItem.AddChild(title, page);
// v10 and later
var child = outlineItem.Children.Add(title);
child.View = doc.CreateView(page);
The following example shows how to replace the overload that accepts a page index:
// Before v10
var child = outlineItem.AddChild(title, pageIndex);
// v10 and later
var child = outlineItem.Children.Add(title);
child.View = doc.CreateView(pageIndex);
PdfOutlineItem.Children property
The Children property is now of type PdfOutlineItemCollection instead of a
PdfCollection<PdfOutlineItem>.
As a result, several index-based operations previously provided by PdfCollection<PdfOutlineItem>
are no longer available, including Count, the indexer, and GetAt(int). This change is
intentional. In PDF documents, sibling bookmarks are stored as a doubly linked list rather than an
array. Therefore, operations based on item positions require traversing the list and cannot be
implemented efficiently.
See Collections and object identity for migration guidance.
In most scenarios, it is preferable to iterate the collection directly rather than rely on item indexes. This avoids unnecessary traversal and more accurately reflects how bookmarks are represented internally in a PDF document.
If an index is required during iteration, .NET 9 and later provide the Index() extension method:
foreach (var (index, child) in outlineItem.Children.Index())
{
if (index % 2 == 0)
{
// Process every even-indexed child item.
}
}
For projects targeting earlier .NET versions, use the indexed overload of Select:
foreach (var item in outlineItem.Children.Select((child, index) => new { child, index }))
{
if (item.index % 2 == 0)
{
// Process every even-indexed child item.
}
}
Please note that PdfOutlineItemCollection provides methods for modifying the collection,
including adding, inserting, removing, and clearing child bookmarks.
PdfOutlineItem.ChildCount property
The ChildCount property is now obsolete. Avoid depending on the number of child items whenever
possible. Iterating through child outline items is the recommended approach in most scenarios.
// Before v10
for (int i = 0; i < outlineItem.ChildCount; i++)
{
var childOutlineItem = outlineItem.GetChild(i);
// ...
}
// v10 and later
foreach (var childOutlineItem in outlineItem.Children)
{
// ...
}
If you need the number of child items, use LINQ:
int childCount = outlineItem.Children.Count();
Note that Children.Count() is an O(n) operation because it enumerates all child items.
If you only need to check whether the collection contains any items, use Children.Any() instead:
bool hasChildren = outlineItem.Children.Any();
PdfOutlineItem.GetChild method
The GetChild method is now obsolete. The recommended approach is to use the Children collection
and iterate over its items rather than relying on child indexes.
If you need indexed access for migration purposes, you can obtain the same behavior using LINQ:
var child = item.Children.ElementAt(index);
For scenarios that require multiple index-based lookups, consider materializing the collection first:
var children = item.Children.ToArray();
var child = children[index];
However, iterating over the Children collection remains the preferred approach, as it avoids
unnecessary materialization and aligns with the intended usage of the API.
The method no longer guarantees that repeated calls for the same child return the same object instance. As a result, object identity and reference equality are not guaranteed.
PdfOutlineItem.IndexOfChild methods
All IndexOfChild methods are now obsolete. Instead of relying on child indexes, use the
Children collection and iterate through its items as needed.
PdfOutlineItem.InsertChild methods
All InsertChild methods are now obsolete. To insert child outline items, use the Children
collection and call either PdfOutlineItemCollection.InsertBefore or
PdfOutlineItemCollection.InsertAfter.
When possible, it is recommended to replace index-based insertions with relative positioning.
Instead of inserting an item at a specific index, insert it before or after an existing outline
item. To append a child item to the end of the collection, use PdfOutlineItemCollection.Add.
For migration purposes, you can use code similar to the following:
// Before v10
var child = outlineItem.InsertChild(index, title);
// v10 and later
if (index >= outlineItem.Children.Count())
return outlineItem.Children.Add(title);
var existingChild = outlineItem.Children.ElementAt(index);
return outlineItem.Children.InsertBefore(existingChild, title);
Note that this migration approach requires additional traversals of the Children collection to
locate the target item.
Both InsertBefore and InsertAfter replace all obsolete InsertChild overloads. These methods
accept only the title of the outline item to create and return the new PdfOutlineItem. You can
then configure additional properties, such as the action or destination view, on the returned item.
See the AddChild methods section for examples of configuring actions and destination views on inserted outline items.
PdfOutlineItem.Page property
The Page property is now obsolete. Its value was derived from the Action and View properties.
Retrieving a page from a view (see PdfDocumentView.Page) currently requires enumerating all
document pages and can be slow for large documents.
If you need to determine the destination page for an outline item, you can use the following method (exception handling omitted for brevity):
public static PdfPage? GetDestinationPage(PdfDocument pdf, PdfOutlineItem item)
{
var view = item.View;
if (view is null)
{
var action = item.Action;
if (action is PdfGoToAction gotoAction)
view = gotoAction.GetView().View;
}
if (view is null)
return null;
var page = view.Page;
if (page != null)
return page;
return pdf.Pages[view.PageIndex];
}
PdfOutlineItem.PageIndex property
The PageIndex property is now obsolete. Its value was derived from the Action and View
properties.
Retrieving a page from a view (see PdfDocumentView.Page) currently requires enumerating all
document pages and can be slow for large documents. Determining the index of the resolved page
requires an additional traversal of the page collection.
If you need to determine the destination page index for an outline item, you can use the following method (exception handling omitted for brevity):
private static int GetDestinationPageIndex(PdfDocument doc, PdfOutlineItem item)
{
var view = item.View;
if (view is null)
{
var action = item.Action;
if (action is PdfRemoteGoToAction remoteGotoAction)
view = remoteGotoAction.GetView().View;
else if (action is PdfGoToAction gotoAction)
view = gotoAction.GetView().View;
}
if (view is null)
return -1;
if (view.PageIndex >= 0)
return view.PageIndex;
var viewPageDictString = view.Page?.Dictionary.ToString();
if (viewPageDictString != null)
{
for (int i = 0; i < doc.Pages.Count; i++)
{
var pageDictString = doc.Pages[i].Dictionary.ToString();
if (viewPageDictString == pageDictString)
return i;
}
}
return -1;
}
PdfOutlineItem.Parent property
In previous versions, the Parent property returned the same cached PdfOutlineItem instance.
Starting with version 10, each call creates a new PdfOutlineItem object from the underlying PDF
structure.
Update any code that relies on reference equality or assumes that repeated calls to Parent return
the same object instance.
PdfOutlineItem.RemoveAllChildren method
The RemoveAllChildren method is now obsolete. To remove all child items, use the Children
collection and call its Clear method instead (PdfOutlineItemCollection.Clear).
PdfOutlineItem.RemoveChild method
The RemoveChild method is now obsolete. To remove a child item, use the Children
collection and call its Remove method instead.
PdfOutlineItem.RemoveChildAt method
The RemoveChildAt method is now obsolete. Child items should no longer be accessed by index.
Instead, locate the child item in the Children collection and remove it using the collection's
Remove method.
For migration purposes, replace calls to RemoveChildAt with:
var child = outlineItem.Children.ElementAt(index);
outlineItem.Children.Remove(child);
Note that this replacement requires an additional traversal of the Children collection to locate
the item before it can be removed.
PdfPage
The PdfPage class exposes many collections through its methods and properties, and therefore it
is significantly affected by the updates to the collection implementations. A large number of its
collection-related members have been revised to align with the new unified collection model.
The following members are affected:
- AssociatedFiles property
- ControlCount property
- Controls property
- GetChars method
- GetControl method
- GetObjects methods
- GetPaintedImages method
- GetSortedControls method
- GetSortedWidgets method
- GetWidget method
- GetWords method
- GetXObject method
- WidgetCount property
- Widgets property
- XObjectCount property
- XObjects property
PdfPage.AssociatedFiles property
The property now returns a PdfFileSpecificationCollection instead of
PdfList<PdfFileSpecification?>.
See Collections and object identity for migration guidance.
PdfPage.ControlCount property
The ControlCount property is now obsolete. Use the GetControls() method together with the LINQ
Count() method to obtain the number of controls associated with a page.
PdfPage.Controls property
The Controls property is now obsolete. Instead of accessing a PdfCollection<PdfControl> through
this property, use the new GetControls() method to retrieve the controls associated with a page.
PdfPage.GetChars method
The GetChars method now returns IEnumerable<PdfTextData> instead of
PdfCollection<PdfTextData>.
See Collections and object identity for migration guidance.
PdfPage.GetControl method
The GetControl method is now obsolete. The recommended approach is to use GetControls() and
iterate through the returned controls instead of relying on control indexes.
If you need indexed access for migration purposes, you can achieve equivalent behavior using LINQ:
var control = page.GetControls().ElementAt(index);
For scenarios that require multiple index-based lookups, consider materializing the collection first:
var controls = page.GetControls().ToArray();
var control = controls[index];
However, iterating over the controls returned by GetControls() remains the preferred approach
because it avoids unnecessary materialization and aligns with the intended usage of the API.
The method also no longer guarantees that repeated requests for the same control return the same object instance. Consequently, object identity and reference equality should not be relied upon.
PdfPage.GetObjects methods
All GetObjects() overloads now return IEnumerable<PdfTextData> instead of
PdfCollection<PdfTextData>.
See Collections and object identity for migration guidance.
PdfPage.GetPaintedImages method
The GetPaintedImages method now returns IEnumerable<PdfPaintedImage> instead of
PdfCollection<PdfPaintedImage>.
See Collections and object identity for migration guidance.
PdfPage.GetSortedControls method
The GetSortedControls method is now obsolete. Use the GetControls method and sort the returned
controls as needed.
To reproduce the same behavior as GetSortedControls, use the following LINQ query:
var sortedControls = page.GetControls()
.OrderBy(w => w.BoundingBox.Top)
.ThenBy(w => w.BoundingBox.Left)
.ToArray();
The query sorts controls by their position on the page, from top to bottom and, within the same row, from left to right.
PdfPage.GetSortedWidgets method
The GetSortedWidgets method is now obsolete. Use the Widgets collection and sort the returned
widgets as needed.
To reproduce the same behavior as GetSortedWidgets, use the following LINQ query:
var sortedWidgets = page.Widgets
.OfType<PdfWidget>()
.OrderBy(w => w.BoundingBox.Top)
.ThenBy(w => w.BoundingBox.Left)
.ToArray();
The query sorts widgets by their position on the page, from top to bottom and, within the same row,
from left to right. It also filters out null entries from the Widgets collection. Such entries
can occur when a widget cannot be constructed.
PdfPage.GetWidget method
The GetWidget(int) method is now obsolete. To access a widget by index, use the Widgets
collection and its Widgets[int] indexer instead.
PdfPage.GetWords method
The GetWords method now returns IEnumerable<PdfTextData> instead of
PdfCollection<PdfTextData>.
See Collections and object identity for migration guidance.
PdfPage.GetXObject method
The GetXObject method is now obsolete. The recommended approach is to use the XObjects
collection and iterate over its items rather than relying on XObject indexes.
If you need indexed access for migration purposes, you can obtain the same behavior using LINQ:
var xobj = page.XObjects.Where(entry => entry.XObject is not null).ElementAt(index).XObject!;
For scenarios that require multiple index-based lookups, consider materializing the collection first:
var xobjects = page.XObjects.Where(entry => entry.XObject is not null).ToArray();
var xobj = xobjects[index];
However, iterating over the XObjects collection remains the preferred approach, as it avoids
unnecessary materialization and aligns with the intended usage of the API.
The method no longer guarantees that repeated calls for the same XObject return the same object instance. As a result, object identity and reference equality are not guaranteed.
PdfPage.WidgetCount property
The WidgetCount property is now obsolete. Use the Widgets collection and its Count property
instead.
PdfPage.Widgets property
The behavior of PdfWidgetCollection, the return type of the Widgets
property, has changed.
PdfPage.XObjectCount property
The XObjectCount property is now obsolete. Avoid depending on the number of XObjects whenever
possible. Iterating through XObjects is the recommended approach in most scenarios.
// Before v10
for (int i = 0; i < page.XObjectCount; i++)
{
var xobj = page.GetXObject(i);
// ...
}
// v10 and later
foreach (var entry in page.XObjects)
{
var xobj = entry.XObject;
// ...
}
If you need the number of XObjects, use LINQ:
int xobjCount = page.XObjects.Count();
Note that XObjects.Count() is an O(n) operation because it enumerates all XObjects.
If you only need to check whether the collection contains any items, use XObjects.Any() instead:
bool hasXObjects = page.XObjects.Any();
PdfPage.XObjects property
The XObjects property is now of type PdfXObjectMap instead of PdfList<PdfXObject>. This
change better reflects how XObjects are stored in a page's PDF resources.
The new type provides similar functionality but does not support index-based operations.
Another important difference is that the collection semantics have changed. Previously, the
collection exposed only unique PdfXObject instances. It now exposes all name/XObject pairs found
in the underlying PDF structures.
As a result, some PDF files may contain more entries in XObjects than before. This occurs when
the same XObject is referenced multiple times under different names. In such cases, PdfXObjectMap
exposes each name/XObject pair as a separate entry, even when multiple entries refer to the same
underlying XObject.
Member mapping
The following table shows how members of PdfList<PdfXObject> map to members of PdfXObjectMap:
PdfList<PdfXObject> XObjects->PdfXObjectMap XObjectsAdd(PdfXObject)-> no direct replacement; see Adding itemsCount-> use LINQ if needed:Count()
The following PdfList<PdfXObject> members are no longer supported:
Contains(PdfXObject),IndexOf(PdfXObject), andRemove(PdfXObject). See Object identity-based operations.GetAt(int)andRemoveAt(int). See Index-based operations.
The enumerator type for the XObjects collection changed from
IEnumerator<PdfXObject> GetEnumerator()
to
IEnumerator<PdfXObjectEntry> GetEnumerator()
This change allows you to enumerate entries that associate XObject names with PdfXObject
instances.
Object identity-based operations
PdfXObjectMap creates a new PdfXObjectEntry and a new PdfXObject instance each time an entry
is retrieved through the indexer or during enumeration. Because of this behavior, operations that
depend on object identity or instance equality are no longer supported.
Update any code that uses Contains(PdfXObject), IndexOf(PdfXObject), or Remove(PdfXObject) to
work with XObject names and use the indexer and/or enumeration instead.
Index-based operations
PdfXObjectMap does not provide index-based operations. The recommended approach is to enumerate
the collection rather than rely on positional access.
If indexed access is required during migration, you can achieve equivalent behavior using LINQ:
var xobj = page.XObjects.ElementAt(index).XObject;
For scenarios that require multiple indexed lookups, consider materializing the collection first:
var entries = page.XObjects.ToArray();
var xobj = entries[index].XObject;
There is no direct replacement for PdfList<PdfXObject>.RemoveAt(int). Instead, enumerate the map,
locate the entry at the desired position, obtain its name, and remove the corresponding XObject
using PdfXObjectMap.Remove(string):
PdfXObjectMap map = page.XObjects;
var entry = map.ElementAt(index);
map.Remove(entry.Name);
Adding items
PdfXObjectMap does not provide methods for explicitly adding XObjects. Instead, XObjects are
added automatically when you draw them on a page using one of the PdfCanvas.DrawXObject methods.
The library assigns names to automatically added XObjects using the format Xn, where n starts
at 0 and increments for each newly added XObject.
PdfPath
The PdfCollection<PdfSubpath> Subpaths property is now obsolete. Use the new
IEnumerable<PdfSubpath> GetSubpaths() method instead.
See Collections and object identity for migration guidance.
PdfPublicKeyEncryptionInfo
The PdfCollection<PdfRecipientInfo> Recipients property is now obsolete. Use the new
IEnumerable<PdfRecipientInfo> GetRecipients() method instead.
See Collections and object identity for migration guidance.
PdfResetFormAction
The class no longer inherits collection-related members from PdfControlAction. Instead, it now
derives directly from PdfAction and exposes its control collection through the
PdfControlCollection Controls property.
Mapping of old members to new ones:
PdfCollection<PdfControl> Controlsis nowPdfControlCollection ControlsControlCountwas removed. Use theCountproperty of theControlscollection.GetControl(int)was removed. Use the indexer of theControlscollection.AddControl(PdfControl)was removed. UseControls.Add(PdfControl).GetAt(int)was removed. Use indexer access instead.
The Controls collection may construct a new PdfControl instance each time an index is accessed.
Because of this, operations that rely on value comparison are not supported. Update any code that
uses Contains or IndexOf to rely on positional logic instead.
PdfRichMediaAnnotation
The changes in this class affect how rich media annotations are created, configured, and accessed.
PdfRichMediaAnnotation.Assets property
The Assets property is now of type PdfFileSpecificationMap instead of
PdfFileSpecificationCollection. This better reflect the way the collection internally stored in
PDF. The new type exposes a similar set of methods and properties, but several members now behave
differently.
Mapping of old members to new ones:
PdfFileSpecificationCollection Assets->PdfFileSpecificationMap AssetsGet(string)-> removed; use indexer access insteadAdd(PdfFileSpecification)->Add(string, PdfFileSpecification); see note belowRemove(PdfFileSpecification)-> not supported; see note below
The enumerator type for the Assets collection changed from IEnumerator<PdfFileSpecification>
GetEnumerator() to IEnumerator<PdfFileSpecificationEntry> GetEnumerator(), allowing iteration
over key/value pairs rather than values only.
The indexer Assets[string] keeps the same signature, but its operational semantics have changed.
Previously, it searched the entire collection for an item whose
PdfFileSpecification.Specification matched the provided string. Now it performs a direct lookup
by key in the underlying PDF structure. It does not parse values to locate a matching pair. Because
of this change, existing code may no longer obtain the expected value from the indexer if the key
and the entry's PdfFileSpecification.Specification do not match.
The Assets.Add method now requires you to provide the key explicitly. Previously, the key was
derived from the provided value's PdfFileSpecification.Specification, with the -1 suffix
appended repeatedly whenever that key was already in use.
The Assets.Add method also overwrites any existing entry with the same key. Use
Assets.Contains(string) to check whether a key already exists.
The Assets collection creates a new PdfFileSpecificationEntry with a new PdfFileSpecification
instance each time an indexer is accessed or the collection is iterated. Because each lookup
returns a different object instance, operations that rely on value or instance equality are no
longer supported. Update any code that uses Remove(PdfFileSpecification) to operate on the string
key instead.
PdfRichMediaAnnotation.Configurations property
The PdfCollection<PdfRichMediaConfiguration?> Configurations property is now obsolete. Use the
new IEnumerable<PdfRichMediaConfiguration> GetConfigurations() method instead.
See Collections and object identity for migration guidance.
PdfRichMediaConfiguration
The PdfCollection<PdfRichMediaInstance?> Instances property is now obsolete. Use the new
IEnumerable<PdfRichMediaInstance> GetInstances() method instead.
See Collections and object identity for migration guidance.
PdfSpotColor
The ReadOnlyCollection<double> Components property is now obsolete. Use the new double[]
GetComponents() method instead.
PdfStringDrawingOptions
The GetCharacterWidths() method now returns IEnumerable<double> instead of
ICollection<double>?. An empty enumeration now indicates that character widths from the current
canvas font are used without any additional displacement. Previously, the method returned null to
signal the same behavior.
The SetCharacterWidths(IEnumerable<double>) method was updated accordingly; previously it
accepted an ICollection<double> parameter.
PdfSubmitFormAction
PdfSubmitFormAction no longer inherits collection-related members from PdfControlAction. Its
controls are now exposed through the PdfControlCollection Controls property, and the class
derives directly from PdfAction.
This change mirrors the one made to PdfResetFormAction. See the PdfResetFormAction
section for details and migration guidance.
PdfSubpath
The PdfCollection<PdfPathSegment> Segments property is now obsolete. Use the new
IEnumerable<PdfPathSegment> GetSegments() method instead.
See Collections and object identity for migration guidance.
PdfTextData
The GetCharacters and GetCharCodes methods now return IEnumerable<T> instead of
PdfCollection<T>.
See Collections and object identity for migration guidance.
PdfWidget
The AssociatedFiles property is now of type PdfFileSpecificationCollection instead of
PdfList<PdfFileSpecification?>.
See Collections and object identity for migration guidance.
PdfWidgetCollection
PdfWidgetCollection now implements IEnumerable<PdfWidget?> instead of
PdfCollection<PdfWidget>. Despite the change, it still provides the core positional members:
Count, the indexer, Clear, and RemoveAt. The former GetAt method has been removed in favor
of indexer access.
The Remove(PdfWidget) method has also been removed. Because the collection may construct a new
PdfWidget instance each time an element is accessed, operations that rely on value comparison are
not supported. Update any code that uses Remove(PdfWidget), Contains(PdfWidget), or
IndexOf(PdfWidget) to rely on positional logic instead.
PdfXObject
The changes to PdfXObject introduce a dedicated collection type for associated files and change
the return type of the GetObjects() methods to IEnumerable<PdfTextData>.
PdfXObject.AssociatedFiles property
The AssociatedFiles property has changed from PdfList<PdfFileSpecification?> to
PdfFileSpecificationCollection.
See Collections and object identity for migration guidance.
PdfXObject.GetObjects methods
All GetObjects() overloads now return IEnumerable<PdfTextData> instead of
PdfCollection<PdfTextData>.
See Collections and object identity for migration guidance.
XmpArray
The XmpArray class now implements IEnumerable<XmpValue> and provides collection operations
directly. The Values property is obsolete; use the corresponding XmpArray members instead.
Mapping of old members to new ones:
Values.Count-> useCountValues.GetAt(int)-> use the indexerValues.Add(XmpValue)-> useAdd(XmpValue)Values.Remove(int)-> useRemoveAt(int)Values.Clear()-> useClear()Values.Contains(XmpValue)-> not supported; see note belowValues.IndexOf(XmpValue)-> not supported; see note belowValues.Remove(XmpValue)-> not supported; see note below
Each access through the indexer may create a new XmpValue instance. Because of this, operations
that rely on value identity or equality are not supported. Update any code that uses
Contains(XmpValue), IndexOf(XmpValue), or Remove(XmpValue) to rely on positional logic
instead.
XmpMetadata
The Schemas property is now of type XmpSchemaCollection instead of XmpSchemaList. This change
removes all collection-management members that relied on value comparison, such as
Contains(XmpSchema), IndexOf(XmpSchema), and Remove(XmpSchema).
The new type also no longer provides a string indexer, GetAt(index), or Contains(string).
Alternatives are available and listed below.
Mapping of old members to new ones:
XmpSchemaList Schemas->XmpSchemaCollection SchemasSchemas.GetAt(int)-> removed; use indexer access insteadSchemas.Contains(XmpSchema)-> not supported; see note belowSchemas.IndexOf(XmpSchema)-> not supported; see note belowSchemas.Remove(XmpSchema)-> not supported; see note belowSchemas.Remove(int)-> useSchemas.RemoveAt(index)- the
Schemas[string]indexer -> useSchemas.Get(string) Schemas.Contains(string)-> removed; callSchemas.Get(string)and check fornull
The Schemas collection may construct a new XmpSchema instance each time an index is accessed.
Because of this behavior, operations that rely on value comparison are not supported. Update any
code that uses Contains, IndexOf, or Remove to rely on positional logic instead.
XmpSchema
The Properties property is now of type XmpPropertyMap instead of XmpPropertyList. This change
reflects how XMP properties are actually stored inside PDF files: as a keyed map rather than an
ordered list. The new type exposes a similar set of methods and properties, but several members now
behave differently.
In XmpPropertyMap, each entry includes:
- the property name
- the property value
- the namespace prefix
- the namespace URI
Each XmpPropertyMap instance stores the prefix and URI of its owner. This allows the map to
resolve entries referenced by name only, using the owner's namespace information. In
XmpPropertyList, this namespace information was not stored internally and was optional on
XmpProperty objects.
From XmpPropertyList to XmpPropertyMap
After the type change, several API members were removed or replaced.
Index-based API removed:
GetAt(index)-> removed; the new type is key-based, not index-basedRemove(index)-> removed; useRemove(string)instead
Value-based API removed. These relied on object identity or equality, which no longer works because entries are recreated on each lookup:
Contains(XmpProperty)-> not supportedIndexOf(XmpProperty)-> not supportedRemove(XmpProperty)-> not supported
These methods replaced by indexer semantics:
Get(string)-> removed; use the indexer insteadSet(string, XmpValue)-> removed; use the indexer instead
The Add/Set overloads with the description parameter were removed. Descriptions for custom
properties in PDF/A extension schemas must now be added directly to the extension schema, not
through the property map.
Add(string, string, string)->Add(string, string)Add(string, XmpValue, string)->Add(string, XmpValue)Set(string, XmpValue, string)-> removed; use indexer
Behavioral changes
The indexer this[string] and Contains(string) keep their signatures, but their semantics
changed.
Previously they searched the entire collection for a property whose XmpProperty.Name matched the
string. Now they perform a direct key lookup, where the key is implicitly constructed from:
- the provided name
- the schema's namespace prefix
- the schema's namespace URI
The indexer now returns XmpValue? only, without namespace information.
The Properties collection creates a new XmpPropertyEntry with a new XmpPropertyDescriptor
instance each time an indexer is accessed or the collection is iterated. Because each lookup
returns a different object instance, operations that depend on value or instance equality are no
longer supported. Update any code that uses Contains(XmpProperty), IndexOf(XmpProperty), or
Remove(XmpProperty) to operate on the string key instead.
XmpString
The Qualifiers property is now of type XmpPropertyMap instead of XmpPropertyList. For details
about the API and behavioral changes introduced by this type change, see the XmpSchema
section.
XmpString differs in how qualifier namespaces are handled. Unlike properties in an XmpSchema,
string qualifiers do not retain a namespace prefix or namespace URI. The same string value can be
added to multiple arrays or structures, so it cannot reliably carry a single owner namespace.
Because of this, the collection throws an exception if you attempt to add a qualifier with an
explicitly specified namespace.
When saving to an XMP document, the qualifiers associated with an XmpString are written using the
namespace prefix of the containing XMP structure, such as an XmpSchema or XmpStructure.
XmpStructure
The Properties property is now of type XmpPropertyMap instead of XmpPropertyList. For details
about the API and behavioral changes introduced by this type change, see the XmpSchema
section.
Page management
In version 10, page management is centered around the PdfPageCollection type, accessible through
the PdfDocument.Pages property. Several methods and properties previously
exposed directly by PdfDocument have been moved to this collection, and some operations have
changed.
Page operations
Use the PdfDocument.Pages collection to access pages and perform operations such as adding,
inserting, removing, copying, extracting, moving, and swapping pages. The PdfDocument.PageCount
property has also been replaced by Pages.Count.
For example, use PdfDocument.Pages[int] instead of PdfDocument.GetPage(int), and
PdfDocument.Pages.RemoveAt(int) instead of PdfDocument.RemovePage(int).
See the PdfDocument API changes section for the complete list of affected members and migration instructions.
Working with page positions
The new PdfPageCollection may create a new PdfPage instance each time a page is accessed. As a
result, operations that rely on comparing page objects are no longer supported.
Some methods that previously accepted PdfPage objects also have no direct replacement. Update
such code to identify and manipulate pages by their positions in the collection instead.
Page enumeration
The new collection's enumerator may return null entries when a page cannot be constructed from
the underlying PDF data. Previously, such pages appeared as empty PdfPage instances. Review code
that enumerates pages to account for this change.
Bookmark-related changes
Version 10 introduces a redesigned API for working with PDF bookmarks (outlines). The new API separates bookmark collection management from individual bookmark properties, reduces the number of method overloads, and removes operations that cannot be implemented efficiently with the underlying PDF structure.
The changes affect PdfDocument, PdfOutlineItem, and the new PdfOutlineItemCollection type.
The main changes are grouped below.
Bookmark collections
The obsolete PdfDocument.OutlineRoot property has been replaced by
PdfDocument.Outlines, which provides direct access to top-level bookmarks without a synthetic
root item. Similarly, the PdfOutlineItem.Children property now returns
a PdfOutlineItemCollection that supports adding, inserting, removing, and clearing child
bookmarks.
The PdfOutlineItem.AddChild and PdfOutlineItem.InsertChild methods have also been replaced by collection methods. These methods create a bookmark and return the newly created item, which you can then configure as needed.
Index-based operations
The new collection API does not provide index-based access to bookmarks. Instead, iterate through collections directly or materialize them when indexed access is required.
Bookmark destinations and actions
The PdfOutlineItem.Action property now represents only explicitly defined
PDF actions. The new PdfOutlineItem.View property provides access to document view destinations.
The PdfOutlineItem.Page and
PdfOutlineItem.PageIndex properties are now obsolete. Use
PdfOutlineItem.View or PdfOutlineItem.Action, as appropriate, to determine a bookmark's
destination.
Object identity
The new API may create a new PdfOutlineItem instance each time a bookmark is accessed. Code
should not rely on reference equality or assume that repeated calls return the same object
instance.
Layer-related changes
The optional content API has been revised to provide a more flexible way to manage layers and their
configuration. PdfDocument.OptionalContent provides access to a document's optional content
properties, including its layer collection.
The PdfDocument.Layers property and PdfDocument.CreateLayer methods are obsolete. Use
PdfDocument.OptionalContent.Layers to access the collection of layers and create new layers. See
PdfDocument.Layers property and PdfDocument.CreateLayer
methods for migration details.
Layer intents are now represented by intent names (string[]) rather than the PdfLayerIntent
type, which is obsolete. The PdfLayer.GetIntents() method has been replaced by
PdfLayer.GetIntentNames(). See PdfLayer and PdfLayerIntent for
details.
Combo box and list box controls
Combo box and list box controls now use a specialized item collection type,
PdfListItemCollection, to manage their items. The methods previously used to add or clear items
are now obsolete, and the new collection provides the corresponding operations.
These changes affect PdfComboBox and PdfListBox.
AddItem and AddItems methods
All AddItem and AddItems methods in PdfComboBox and PdfListBox are now obsolete. To add
items, use the Items collection and call the corresponding PdfListItemCollection.Add method.
Mapping of old members to new ones:
AddItem(PdfListItem)->Items.Add(PdfListItem)AddItem(string)->Items.Add(string)AddItems(PdfListItem[])->Items.Add(IEnumerable<PdfListItem>)AddItems(IEnumerable<PdfListItem>)->Items.Add(IEnumerable<PdfListItem>)AddItems(string[])->Items.Add(IEnumerable<string>)AddItems(IEnumerable<string>)->Items.Add(IEnumerable<string>)
ClearItems method
The ClearItems method in both PdfComboBox and PdfListBox is now obsolete. To remove all
items, call PdfListItemCollection.Clear on the Items collection instead.
Items property
The Items property in both classes is now of type PdfListItemCollection instead of
PdfCollection<PdfListItem>.
See Collections and object identity for migration guidance.
XMP metadata changes
The API for working with XMP metadata has been revised to better reflect the structure of XMP documents and to provide collection types suited to the underlying data.
The changes affect XmpArray, XmpMetadata, XmpSchema, XmpString, and XmpStructure.
Collection type changes
Several properties now expose new collection types that better reflect the underlying data:
XmpSchemaCollectionreplacesXmpSchemaListinXmpMetadata.Schemas.XmpPropertyMapreplacesXmpPropertyListin thePropertiesproperties ofXmpSchemaandXmpStructureand in theQualifiersproperty ofXmpString.
The XmpArray class also provides collection operations directly, making the obsolete Values
property unnecessary.
Changes to collection access
Several collection members have been removed or replaced:
- Some collections no longer provide
GetAt(index)or index-based removal. XmpPropertyMapuses property names as keys. Its indexer replaces the previousGet(string)andSet(string, XmpValue)methods.- The string indexer on
XmpMetadata.Schemashas been replaced byGet(string). XmpArraynow provides an indexer and collection-management methods directly.
See the sections for XmpArray, XmpMetadata, XmpSchema, and XmpString for the complete member mappings.
Changes to collection behavior
Some collection operations that previously relied on object identity or equality are no longer supported.
The updated collections may create new objects when entries are accessed or enumerated. Consequently, operations that accept an object instance may no longer work as expected.
Use positional operations for arrays and key-based operations for properties instead. For example,
use XmpArray.RemoveAt(index) to remove an array item or remove a property by its string key.
Namespace handling changes
XmpPropertyMap stores the namespace prefix and URI of its owning schema or structure. Property
lookup uses the property name together with this namespace information, so callers do not need to
specify the namespace for each lookup.
String qualifiers follow different rules. An XmpString qualifier does not retain its own
namespace prefix or URI, so attempting to add a qualifier with an explicitly specified namespace
throws an exception. When the XMP document is saved, the qualifier is written using the namespace
prefix of its containing structure.
See the XmpSchema and XmpString sections for details.
Visit our
LinkedIn page |
Telegram channel |
Google Group