1
+ using Syncfusion . Drawing ;
2
+ using Syncfusion . Pdf ;
3
+ using Syncfusion . Pdf . Interactive ;
4
+ using Syncfusion . Pdf . Parsing ;
5
+ class Program
6
+ {
7
+ static void Main ( string [ ] args )
8
+ {
9
+ // Load the PDF document from disk.
10
+ using ( FileStream docStream = new FileStream ( Path . GetFullPath ( @"Data/Input.pdf" ) , FileMode . Open , FileAccess . Read ) )
11
+ {
12
+ // Load the PDF document into memory.
13
+ PdfLoadedDocument loadedDocument = new PdfLoadedDocument ( docStream ) ;
14
+
15
+ // Access the root bookmark collection of the document.
16
+ PdfBookmarkBase bookmarks = loadedDocument . Bookmarks ;
17
+
18
+ // Move a bookmark from index 2 to index 0 (reorder).
19
+ MoveBookmark ( bookmarks , 2 , 0 , loadedDocument ) ;
20
+
21
+ // Remove a bookmark by its title (removes the first match found in hierarchy).
22
+ RemoveBookmarkByTitle ( bookmarks , "Bookmark To Remove" ) ;
23
+
24
+ //Create file stream.
25
+ using ( FileStream outputFileStream = new FileStream ( Path . GetFullPath ( @"Output/Output.pdf" ) , FileMode . Create , FileAccess . ReadWrite ) )
26
+ {
27
+ loadedDocument . Save ( outputFileStream ) ;
28
+ }
29
+
30
+ loadedDocument . Close ( true ) ;
31
+ }
32
+ }
33
+
34
+ // Moves a bookmark from one index to another within its parent collection.
35
+ static void MoveBookmark ( PdfBookmarkBase parentCollection , int fromIndex , int toIndex , PdfLoadedDocument document )
36
+ {
37
+ if ( fromIndex == toIndex ) return ; // No move required if indices are the same.
38
+
39
+ // Safely cast the bookmark to be moved.
40
+ PdfLoadedBookmark bookmarkToMove = parentCollection [ fromIndex ] as PdfLoadedBookmark ;
41
+ if ( bookmarkToMove == null ) return ;
42
+
43
+ // Remove the bookmark from its original location.
44
+ parentCollection . RemoveAt ( fromIndex ) ;
45
+
46
+ // Remove any existing bookmark with the same title at the new location to avoid duplicates.
47
+ RemoveBookmarkByTitle ( parentCollection , bookmarkToMove . Title ) ;
48
+
49
+ // Insert the bookmark at the new index.
50
+ PdfBookmark newBookmark = parentCollection . Insert ( toIndex , bookmarkToMove . Title ) ;
51
+ newBookmark . TextStyle = bookmarkToMove . TextStyle ;
52
+ newBookmark . Color = bookmarkToMove . Color ;
53
+
54
+ // Set the destination (page location/zoom) for the moved bookmark.
55
+ newBookmark . Destination = bookmarkToMove . Destination ?? new PdfDestination ( document . Pages [ 0 ] )
56
+ {
57
+ Location = bookmarkToMove . Destination ? . Location ?? new PointF ( 0 , 0 ) ,
58
+ Zoom = bookmarkToMove . Destination ? . Zoom ?? 1F
59
+ } ;
60
+
61
+ // Move all child bookmarks recursively.
62
+ foreach ( PdfBookmark child in bookmarkToMove )
63
+ {
64
+ AddBookmark ( newBookmark , child , document ) ;
65
+ }
66
+ }
67
+
68
+ // Clones an existing bookmark (including all descendants) and adds it to a parent.
69
+ static void AddBookmark ( PdfBookmark parent , PdfBookmark bookmark , PdfLoadedDocument document )
70
+ {
71
+ // Remove any even-closer duplicate title children before insertion.
72
+ RemoveBookmarkByTitle ( parent , bookmark . Title ) ;
73
+
74
+ PdfBookmark newChild = parent . Insert ( parent . Count , bookmark . Title ) ;
75
+ newChild . Destination = bookmark . Destination ?? new PdfDestination ( document . Pages [ 0 ] )
76
+ {
77
+ Location = new PointF ( 0 , 0 ) ,
78
+ Zoom = 1F
79
+ } ;
80
+ newChild . TextStyle = bookmark . TextStyle ;
81
+ newChild . Color = bookmark . Color ;
82
+
83
+ // Recursively clone and add children.
84
+ foreach ( PdfBookmark child in bookmark )
85
+ {
86
+ AddBookmark ( newChild , child , document ) ;
87
+ }
88
+ }
89
+
90
+ // Removes the first occurrence of a bookmark with the specified title from a parent (searches recursively).
91
+ static void RemoveBookmarkByTitle ( PdfBookmarkBase parent , string title )
92
+ {
93
+ for ( int i = 0 ; i < parent . Count ; )
94
+ {
95
+ if ( parent [ i ] . Title == title )
96
+ {
97
+ parent . RemoveAt ( i ) ;
98
+ continue ;
99
+ }
100
+ if ( parent [ i ] is PdfBookmark child )
101
+ {
102
+ RemoveBookmarkByTitle ( child , title ) ; // Recurse for children
103
+ }
104
+ i ++ ;
105
+ }
106
+ }
107
+ }
0 commit comments