How to Define a PDF Outline Using MigraDoc

跟風遠走 提交于 2019-12-05 19:28:41

I used a hack: added white text on white ground with a font size of 0.001 or so to get outlines that are actually invisible to the user.

For a perfect solution, mix PDFsharp and MigraDoc code. The hack works for me and is much easier to implement.

I realized after reading ThomasH's answer that I am already mixing PDFSharp and MigraDoc code. Since I am utilizing a PdfDocumentRenderer, I was able to add a custom outline to the PdfDocument property of that renderer. Here is an example of what I ended up doing to create a custom outline:

var document = new Document();
// Populate the MigraDoc document here
...

// Render the document
var renderer = new PdfDocumentRenderer(false, PdfFontEmbedding.Always)
{
    Document = document
};
renderer.RenderDocument();

// Create the custom outline
var pdfSharpDoc = renderer.PdfDocument;
var rootEntry = pdfSharpDoc.Outlines.Add(
    "Level 1 Header", pdfSharpDoc.Pages[0]);
rootEntry.Outlines.Add("Level 2 Header", pdfSharpDoc.Pages[1]);

// Etc.

// Save the document
pdfSharpDoc.Save(outputStream);

I've got a method that is slightly less hacked. Here's the basic method:

1) Add a bookmark, save into a list that bookmark field object and the name of the outline entry. Do not set a paragraph .OutlineLevel (or set as bodytext)

// Defined previously
List<dynamic> Bookmarks = new List<dynamic>();

// In your bookmarking method, P is a Paragraph already created somewhere
Bookmarks.Add(new { Bookmark = P.AddBookmark("C1"), Name = "Chapter 1", Depth = 0 });

2) At the end of your Migradoc layout, before rendering, prepare the pages

pdfwriter.PrepareRenderPages();

3) Build a dictionary of the Bookmark's parent's parent (This will be a paragraph) and pages (pages will be initialized to -1)

var Pages = Bookmarks.Select(x=> ((BookmarkField)x).Bookmark.Parent.Parent).ToDictionary(x=>x, x=>-1);

4) Now fill in those pages by iterating through the objects on each page, finding the match

for (int i = 0; i < pdfwriter.PageCount; i++)
    foreach (var s in pdfwriter.DocumentRenderer.GetDocumentObjectsFromPage(i).Where(x=> Pages.ContainsKey(x))
        Pages[s] = i-1;

5) You've now got a dictionary of Bookmark's parent's parents to page numbers, with this you can add your outlines directly into the PDFSharp document. This also iterates down the depth-tree, so you can have nested outlines

foreach(dynamic d in Bookmarks)
{
    var o = pdfwriter.PdfDocument.Outlines;
    for(int i=0;i<d.Depth;i++)
        o = o.Last().Outlines;
    BookmarkField BK = d.Bookmark;
    int PageNumber = Pages[BK.Parent.Parent];
    o.Add(d.Name, pdfwriter.PdfDocument.Pages[PageNumber], true, PdfOutlineStyle.Regular);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!