WPF DocumentViewer: навигация по внутренней ссылке неточная при первом щелчке

В WPF у меня есть DocumentViewer внутри элемента управления Frame. DocumentViewer показывает документ XPS, созданный с помощью MS Word. Документ содержит оглавление, помогающее перемещаться по документу.

DocumentViewer позволяет пользователю щелкать эти ссылки и переходить к соответствующим страницам, если DocumentViewer размещен в элементе управления, который позволяет осуществлять навигацию (например, фрейм).

Когда пользователь перемещается в первый раз, 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 содержит оглавление и две главы по 40 страниц между ними. Проблема становится понятной при переходе ко второй главе (она меньше на 3 страницы).


person Chris    schedule 08.04.2015    source источник
comment
Вы когда-нибудь находили решение этой проблемы? Я сталкиваюсь с тем же самым   -  person Dave_750    schedule 25.11.2015
comment
@ Dave_750 Привет, Дэйв! Нет, к сожалению, нет. Это все еще нерешенная проблема в нашем продукте; (   -  person Chris    schedule 10.12.2015
comment
Спасибо, что вернулись. Я тоже ничего не нашел. Если это поможет, я отобразил xps в элементе управления веб-браузера, и он работает нормально, за исключением того, что мне нужно подождать 5 секунд, пока он полностью загрузится, иначе он все равно перейдет в неправильное место. Еще пришлось добавить в конец пустую страницу. Стиль тоже был PITA ...   -  person Dave_750    schedule 11.12.2015


Ответы (1)


Спустя почти два года я вернулся к этой проблеме и нашел решение.

Как видно из моего исходного сообщения, я использовал 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;
person Chris    schedule 21.02.2017