В WPF у меня есть DocumentViewer внутри элемента управления Frame. DocumentViewer показывает документ XPS, сгенерированный с помощью MS Word. Документ содержит таблицу содержимого, чтобы помочь перемещаться по документу.
DocumentViewer позволяет пользователю щелкнуть эти ссылки и перейти к соответствующим страницам, если DocumentViewer помещен в элемент управления, который позволяет осуществлять навигацию (например, Frame).
Когда пользователь переходит в первый раз, DocumentViewer не точно переходит в связанное местоположение. Чем дальше в документе, тем больше становится пространство между местом прыжка и фактическим местоположением. Похоже, что он отключен на определенную сумму за страницу. После этой первой ссылки нажмите, навигация работает отлично.
При навигации по навигационным кнопкам на кадре точность привязки ведет себя снова, как только загрузится самое первое представление.
Согласно этому сообщению, после первого щелчка по ссылке создается новый DocumentViewer. Кажется, что это создает экземпляр, который работает так, как ожидалось.
Почему исходный экземпляр не точно выполняет навигацию и как это решить?
Ниже приведенный ниже код можно использовать для воспроизведения проблемы.
XAML внутри окна:
<Frame>
<Frame.Content>
<DocumentViewer Name="docViewer" />
</Frame.Content>
</Frame>
Код позади:
public MainWindow()
{
InitializeComponent();
LoadDoc();
}
private void LoadDoc()
{
XpsDocument xpsDoc = new XpsDocument("test.xps", FileAccess.Read);
docViewer.Document = xpsDoc.GetFixedDocumentSequence();
}
Документ test.xps содержит TOC и две главы с примерно 40 страницами между ними. Проблема становится понятной при навигации по второй главе (она отключена на 3 страницы).
Спустя почти два года я пересмотрел эту проблему и нашел решение.
Как видно из моего первоначального сообщения, я использовал Frame
с его содержимым, установленным в DocumentViewer
. Frame
используется для навигации по документу XPS.
Некоторые детали:
Когда документ загружается в первый раз, фактическое Content
Frame
устанавливается в DocumentViewer
. Source
Frame
равен null
. При нажатии ссылки в документе Frame
перемещается к местоположению, но имеет низкую точность, как описано в моем вопросе выше. За кулисами Frame
изменил свой Content
на экземпляр FixedDocumentSequence
и его Source
установлен на щелчок Uri
. С этого момента навигация работает совершенно точно.
Решение:
Решение на самом деле очень простое. Вместо того, чтобы помещать DocumentViewer
внутри Frame
и устанавливать свойство DocumentViewer.Document
на фактическое значение FixedDocumentSequence
, свойство Frame.Source
должно быть установлено в Uri
FixedDocumentSequence
.
FixedDocumentSequence
реализует явное свойство интерфейса IUriContext.BaseUri
которое можно использовать для извлечения Uri
.
В моем коде я использую привязку для установки источника:
<UserControl x:Class="XPSDocumentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:System.Windows.Markup;assembly=System.Xaml" >
<Grid>
<Frame Margin="5" NavigationUIVisibility="Hidden"
Source="{Binding Path=Document.(base:IUriContext.BaseUri)}" />
</Grid>
</UserControl>
В коде позади вы можете сделать то же самое, выполнив следующее:
XpsDocument xpsDoc = new XpsDocument(Path, FileAccess.Read);
FixedDocumentSequence document = xpsDoc.GetFixedDocumentSequence();
frame.Source = ((System.Windows.Markup.IUriContext)document).BaseUri;