In WPF I have a DocumentViewer inside a Frame control. The DocumentViewer shows an XPS document generated with MS Word. The document contains a Table of Content to help navigate through the document.
The DocumentViewer allows the user to click these links and navigate to the corresponding pages, as long as the DocumentViewer is placed in a control that allows for navigation (e.g. a Frame).
When the user navigates for the first time, the DocumentViewer does not jump accurately to the linked location. The further away in the document, the larger the space between the jumped location and the actual location becomes. It looks like it is off by a certain amount per page. After this first link click, the navigation works perfectly fine.
When navigating back using the navigation buttons on the frame, the link accuracy behaves pore again as soon as the very first view is loaded.
According to this post, a new DocumentViewer is being created after clicking on the link for the first time. It seems that that creates an instance that works as expected.
Why is the initial instance not navigating accurately and how to solve this?
The code snipped below can be used to reproduce the issue.
XAML inside a Window:
<Frame>
<Frame.Content>
<DocumentViewer Name="docViewer" />
</Frame.Content>
</Frame>
Code behind:
public MainWindow()
{
InitializeComponent();
LoadDoc();
}
private void LoadDoc()
{
XpsDocument xpsDoc = new XpsDocument("test.xps", FileAccess.Read);
docViewer.Document = xpsDoc.GetFixedDocumentSequence();
}
The test.xps document contains a TOC and two chapters with around 40 pages in between them. The issue becomes clear when navigating to the second chapter (it is off by 3 pages).
After almost two years I've revisited this issue and found the solution.
As can be seen in my original post, I used a
Frame
with its content set to aDocumentViewer
. TheFrame
is used to enable navigation within the XPS document.Some details:
When the document loads for the first time, the actual
Content
of theFrame
is set to theDocumentViewer
. TheSource
of theFrame
isnull
. When clicking a link in the document, theFrame
navigates to the location, but has poor accuracy, as described in my question above. Behind the scenes, theFrame
has changed itsContent
to an instance ofFixedDocumentSequence
and itsSource
is set to the clickedUri
. From now on, the navigation works perfectly accurate.The solution:
The solution is actually very simple. Instead of putting a
DocumentViewer
inside theFrame
and setting theDocumentViewer.Document
property to the actualFixedDocumentSequence
, theFrame.Source
property should be set to theUri
of theFixedDocumentSequence
.FixedDocumentSequence
implements the explicit interface propertyIUriContext.BaseUri
that can be used to retrieve theUri
.In my code, I use a binding to set the source:
In code behind you could accomplish the same by doing this: