Skip to main content

Annotations, forms and redaction

Users pick a tool from the toolbar and draw on the page. Every edit takes part in undo and redo, and is written to the file on save.

Annotation methods take 0-based page indexes and PDF page coordinates: the origin is the bottom-left corner of the page and the unit is the PDF point (1/72 inch).

Tools

ActiveTool is the tool the next pointer gesture applies. The built-in toolbar reads and writes the same property, so your own controls can arm any tool even with the toolbar hidden. SetToolCommand sets it from a command parameter, either the PdfViewerTool value or its name. ActiveTool stays None while CanEditAnnotations is false.

PdfViewerToolGestureResult
Highlight, Underline, Strikeout, SquigglyDrag across textA text markup annotation in the tool's colour.
RedactDrag across textRemoves the covered content from the page. See Redaction.
DrawDrag freehandAn ink annotation with DrawStrokeColor and DrawStrokeWidth.
ShapeDrag a boxThe shape in SelectedShapeType: Line, Arrow, Rectangle, Circle, Polygon, Star or Text. A rectangle when none is set.
TextClick or dragA text box with the TextAnnotation* typography.
NoteClickA sticky note with an in-place editor and colour swatches.
LinkDrag a boxA link annotation. A dialog asks for the URL.
StampClickA rubber stamp from the toolbar dropdown. See Stamps.
NoneClick or drag an annotationSelect, move, resize, restyle, copy, paste and delete existing annotations.
<pdf:PdfViewer x:Name="Viewer" ActiveTool="Highlight" />

<Button Content="Draw"
Command="{Binding #Viewer.SetToolCommand}"
CommandParameter="Draw" />

Annotations created in other applications such as Acrobat or Preview can be edited too. They keep their author, dates, subject, opacity and flags, and shapes keep their own appearance, such as dashed or cloudy borders, when moved or resized.

Tool visibility

Each tool has its own visibility property, so you can offer a subset of the toolbar.

PropertyTool
IsHighlightToolVisibleHighlight
IsUnderlineToolVisibleUnderline
IsStrikethroughToolVisibleStrikeout
IsSquigglyToolVisibleSquiggly
IsRedactToolVisibleRedact
IsDrawToolVisibleDraw
IsShapeToolVisibleShape
IsTextToolVisibleText box
IsNoteToolVisibleSticky note
IsLinkToolVisibleLink
IsStampToolVisibleStamp

To disable editing altogether rather than hide tools, use IsReadOnly or AllowAnnotationEditing. See Document permissions.

Markup from a selection

Selecting text shows a context menu with the markup tools. The same operations are available from code and apply to the current selection. Each returns the new annotation's index on the page, or -1 on failure. Colours are PdfAnnotationColor values with R, G, B and A byte components.

MethodDescription
HighlightSelectionAsync(PdfAnnotationColor? color = null)Highlights the selection.
UnderlineSelectionAsync(PdfAnnotationColor? color = null)Underlines the selection.
StrikeoutSelectionAsync(PdfAnnotationColor? color = null)Strikes out the selection.
SquigglySelectionAsync(PdfAnnotationColor? color = null)Adds a squiggly underline to the selection.
RedactSelectionAsync(PdfAnnotationColor? color = null)Redacts the selection.

When color is null, the matching colour property (HighlightColor and so on) is used.

await Viewer.HighlightSelectionAsync();
await Viewer.UnderlineSelectionAsync(new PdfAnnotationColor(0, 0, 255, 255));

Sticky notes

MethodDescription
AddStickyNoteAsync(int pageIndex, double pdfX, double pdfY, string text, PdfAnnotationColor? color = null)Adds a sticky note at a PDF-space position. Returns the annotation index, or -1.
UpdateStickyNoteAsync(int pageIndex, int annotIndex, string? text, PdfAnnotationColor? color)Changes a note's text or colour.
GetAnnotationsAsync(int pageIndex, CancellationToken)Lists a page's annotations as PdfAnnotationInfo items, with AnnotationIndex, Type, Bounds, Color, Contents and Author.
int index = await Viewer.AddStickyNoteAsync(0, 72, 720, "Check this figure");
await Viewer.UpdateStickyNoteAsync(0, index, "Checked", null);

Stamps

The Stamp dropdown offers a list of labels such as Approved, Draft and Received, a style selector and an Include date toggle. Stamps are saved as standard /Stamp annotations, so other readers render and move them.

PropertyTypeDefaultDescription
StampLabelsIReadOnlyList<string>DefaultStampLabelsLabels offered by the dropdown. Drawn in capitals.
StampColorPdfAnnotationColor?nullColour for every stamp. null picks one by label: green for the built-in approval labels (Approved, Completed, Paid, Received, Reviewed, Final, For Public Release), blue for the built-in status labels (Draft, For Comment, As Is, Experimental, Departmental, Copy), and red for everything else, including your own labels.
StampStylePdfStampStyleClassicLook of new stamps: Classic, Flat, Outline, Legal or Pill. Kept with each stamp.
IncludeStampDateboolfalseAdds today's date as a second line to new stamps.
StampDateFormatstringdd MMM yyyy.NET date format for the date line, invariant culture.

AddStampAsync(int pageIndex, string label, double pdfX, double pdfY, PdfAnnotationColor? color = null, PdfStampStyle? style = null, bool? includeDate = null) adds a stamp centred on a PDF-space point. Arguments left null fall back to the properties above.

Viewer.StampLabels = new[] { "Approved", "Rejected", "Paid" };
await Viewer.AddStampAsync(0, "Approved", 300, 700, includeDate: true);

Shapes and text

Shapes are saved with their standard PDF subtypes (/Square, /Circle, /Line, /Polygon), so they stay editable in other readers. Text boxes are /FreeText. Curved lines are saved as /Stamp. ShapeSubtypeMode chooses how shapes that carry text are written.

PdfShapeSubtypeModeDescription
AutoStandard subtypes for shapes without text, /Stamp for shapes with text. This matches what macOS Preview does.
StandardStandard subtypes for everything, text included. The text is lost if another reader edits the shape.
StrictStandard subtypes only. Text cannot be added to shapes and lines cannot be curved.

Non-Latin text in text boxes, shapes and stamps (Cyrillic, Greek, CJK and so on) is embedded as a font subset, so it renders the same in every reader.

Default colours and typography

PropertyTypeDefaultDescription
HighlightColorPdfAnnotationColorYellow, 50% alphaHighlight colour.
UnderlineColorPdfAnnotationColorGreenUnderline colour.
StrikeoutColorPdfAnnotationColorRedStrikeout colour.
SquigglyColorPdfAnnotationColorBlueSquiggly colour.
DrawStrokeColorPdfAnnotationColorRedFreehand stroke colour.
DrawStrokeWidthfloat2.0Freehand stroke width in PDF points.
ShapeFillColorPdfAnnotationColor?WhiteShape fill. null is none.
ShapeStrokeColorPdfAnnotationColor?BlackShape stroke. null is none.
ShapeStrokeWidthfloat2.0Shape stroke width in PDF points.
SelectedShapeTypeShapeTypeNoneShape drawn by the Shape tool.
TextAnnotationFillColorPdfAnnotationColor?nullText box fill. null is none.
TextAnnotationStrokeColorPdfAnnotationColor?nullText box border. null is none.
TextAnnotationStrokeWidthfloat1.0Text box border width.
TextAnnotationTextColorPdfAnnotationColorBlackText box text colour.
TextAnnotationFontstringHelveticaText box font.
TextAnnotationFontSizefloat12Text box font size.
TextAnnotationFontAttributesFontAttributesNoneBold, italic and similar attributes.
TextAnnotationTextAlignTextAnnotationAlignmentCenterText box alignment.
NoteColorPdfAnnotationColorYellowSticky note colour.

The toolbar's colour picker writes to the same properties.

Redaction

The Redact tool and RedactSelectionAsync remove content rather than cover it. The redacted characters are removed from the page, along with images under the area. Vector paths and form XObjects are removed only when fully covered.

With RedactionRemovesHiddenInformation set to true (the default), a redaction also removes the copies of page content a PDF can keep elsewhere: the tagged structure tree, the page's embedded thumbnail, and the document metadata (title, author, keywords). Outline titles and attachments are not touched.

Redactions are undoable while IsRedactionUndoEnabled is true. Each redaction keeps a copy of the document as it was before, so the history is bounded separately by MaxRedactionUndoSteps.

Forms

Interactive form fields can be filled with the pointer and keyboard. Tab into the document reaches the first field on the page, Tab and Shift+Tab move between fields with a visible focus ring, and Esc or tabbing past the last field leaves the form. Form edits take part in undo and redo and are written on save.

AllowFormEditing turns form filling off. Form filling is not available in the browser.

Undo and redo

Annotation edits, form field edits and redactions are recorded. Bookmarks are not.

MemberDescription
Undo() / Redo()Applies the previous or next history entry. UndoAsync() and RedoAsync() await it.
CanUndo / CanRedoWhether there is an entry to apply. Bindable.
UndoRedoStateChangedRaised when either changes.
MaxUndoStepsUndo history depth, 0 to 1000. Default 100. 0 disables undo and redo.
MaxRedactionUndoStepsHow many redactions stay undoable, 0 to 100. Default 10. The most recent ones are kept.
IsRedactionUndoEnabledWhether redactions are recorded at all. Default true.

Errors

Edits made with the pointer run in the background, so there is nothing to await. Subscribe to AnnotationError to be told when one fails. Its args include Operation, Message and the underlying Exception.

Viewer.AnnotationError += (_, e) =>
ShowToast($"{e.Operation} failed: {e.Message}");

Output compatibility

Every annotation is saved with an appearance stream, so edits render in Acrobat, Preview, Chrome and other readers.

Editing an annotation created by another application rebuilds its appearance. Any reply chain (/Popup, /IRT) attached to it is dropped, and the annotation moves to the end of the page's annotation order.

See also