Search code examples
wpfxpsdocumentviewer

WPF DocumentViewer loses custom style after internal link use


Hi want to build a small application, that allows to navigate through filesystem and displays several documents. One type of document i want to show, is xps. DocumentViewer is doing well. In combination with a Frame the viewer can handle internal links (included in the xps documents.). For my Application i build a custom toolbar (zoom, page, fitsize ...), to have a one toolbar for every kind of document. So i needed to remove the toolbar of the documentViewer. Below is the code.

<Style x:Key="{x:Type DocumentViewer}"
   TargetType="{x:Type DocumentViewer}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DocumentViewer}">
                <Border BorderThickness="{TemplateBinding BorderThickness}"
            BorderBrush="{TemplateBinding BorderBrush}"
            Focusable="False">
                    <ScrollViewer 
                      CanContentScroll="true"
                      HorizontalScrollBarVisibility="Auto"
                      x:Name="PART_ContentHost"
                      IsTabStop="true">
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

That works fine, but after activating a link in the xps, the DocumentViewer Toolbar appears again. How to avoid that?


Solution

  • The problem is that the navigation service creates a new standard DocumentViewer after clicking on a link for the first time. This happens even when you use a component derived from DocumentViewer in your XAML.

    You can work around this issue by manually resetting the style in your navigation container's LayoutUpdated event

    XAML

    <Frame LayoutUpdated="OnFrameLayoutUpdated">
        <Frame.Content>
            <DocumentViewer ... />
        </Frame.Content>
    </Frame>
    

    Code behind

    private void OnFrameLayoutUpdated(object sender, EventArgs e)
    {
        var viewer = GetFirstChildByType<DocumentViewer>(this);
        if (viewer == null) return;
        viewer.Style = (Style) FindResource("DocumentViewerStyle");
    }
    
    private T GetFirstChildByType<T>(DependencyObject prop) where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(prop); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild((prop), i) as DependencyObject;
            if (child == null)
                continue;
    
            T castedProp = child as T;
            if (castedProp != null)
                return castedProp;
    
            castedProp = GetFirstChildByType<T>(child);
    
            if (castedProp != null)
                return castedProp;
        }
        return null;
    }