Displaying an XPS Document on the Microsoft Surface


As a part of an application I am prototyping, I ran into the need recently to display a document inside a ScatterViewItem on the the Microsoft Surface. Since there is (intentionally) no built-in way to display HTML content on the Surface, and displaying a Word document did not seem feasible, I settled on using an XML document, and using the WPF DocumentViewer control.

This seems pretty easy, right? Just put a DocumentViewer inside your ScatterViewItem, load the document into the DocumentViewer, and you’re done. Couldn’t be easier.

Well, displaying the XML document was indeed that easy. Unfortunately, as I expected, the DocumentViewer would not respond to touch at all. I posted a question to the MSDN Surface forums about this, and did not receive any response for several weeks.   The response I finally did receive was that I would have to develop a User Control, and handle the touch events myself.

Not being one to take advice, I decided to try another approach – I decided to see if I could hack the ControlTemplate for the DocumentViewer in such a way as to have it support touch (keep in mind that I am a relative noob when it comes to all of this WPF/Styles/ControlTemplate stuff).

So I created a simple Surface project in VS2008, and modified the SurfaceWindow1.xaml file to have a ScatterView control, containing a single DocumentViewer control, as shown below:

<s:SurfaceWindow x:Class="SurfaceDocumentViewer.SurfaceWindow1"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:s=http://schemas.microsoft.com/surface/2008
    Title="SurfaceDocumentViewer" Loaded="SurfaceWindow_Loaded">
  <s:SurfaceWindow.Resources>
    <ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
  </s:SurfaceWindow.Resources>
    <s:ScatterView Background="{StaticResource WindowBackground}" >
        <DocumentViewer Margin=”15” Height="Auto" Name="docViewer" Width="Auto" />
    </s:ScatterView>
</s:SurfaceWindow>

Note that I added a margin around the DocumentViewer so that there would be something to grab on to in order to resize the ScatterViewItem. 

I then opened the project in Expression Blend so that I could get a copy of the “default” style/template for the DocumentViewer control. Opening the project in Blend, right click on the DocumentViewer, and select Edit Template | Edit a Copy…, as shown

2

Name the style (I used SurfaceDocumentViewerStyle), and define a location for it (I left it in the SurfaceWindow1.xaml file), as shown below.

3

Click OK, then save your changes and close Expression Blend.

Returning to Visual Studio, you will get a message that the project has been changed outside of Visual Studio. Click Reload to load the changes into Visual Studio. Opening SurfaceWindow1.xaml in design view, you should now see a <Style> element under <s:SurfaceWindow.Resources>, and within that, a ControlTemplate for the DocumentViewer. There are several parts to the ControlTemplate:

  • A ContentControl for the toolbar, that loads from an external assembly.
  • A ScrollViewer named PART_ContentHost that is the container for the actual document display
  • A DockPanel that provides background for PART_ContentHost
  • Another ContentControl names PART_FindToolBarHost where the search box is hosted

The only part important to me was the ScrollViewer. I also wanted to get rig of the toolbar and the search box in order to keep things as clean as possible. So I deleted the other parts.

Here then is the key step to making the DocumentViewer touch aware: I replaced the ScrollViewer with s:SurfaceScrollViewer. My new ControlTemplate now looks as shown below:

<Style x:Key="SurfaceDocumentViewerStyle" BasedOn="{x:Null}" TargetType="{x:Type DocumentViewer}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="ContextMenu" Value="{DynamicResource {ComponentResourceKey ResourceId=PUIDocumentViewerContextMenu, TypeInTargetAssembly={x:Type System_Windows_Documents:PresentationUIStyleResources}}}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DocumentViewer}">
                <Border Focusable="False" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" >
                    <Grid Background="{TemplateBinding Background}" KeyboardNavigation.TabNavigation="Local">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <s:SurfaceScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" x:Name="PART_ContentHost" IsTabStop="true" TabIndex="1" Focusable="{TemplateBinding Focusable}" Grid.Column="0" Grid.Row="1" CanContentScroll="true" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now, to test this, add an XPS document to your project (mine is name test.xps). Add an assembly reference to ReachFramework (XPS package support), and add using statements to SurfaceWindow1.xaml.cs as shown:


using System.IO;
using System.Windows.Xps.Packaging;

Add the following code to the end of the SurfaceWindow1 constructor to load and display the XPS document:


XpsDocument doc = new XpsDocument("test.xps", FileAccess.Read);
docViewer.Document = doc.GetFixedDocumentSequence();
docViewer.FitToWidth();
doc.Close();

Finally, to make the XPS document resize when you resize the ScatterViewItem, Add an event handler to your DocumentViewer to handle the SizeChanged event, as shown below:


private void docViewer_SizeChanged(object sender, SizeChangedEventArgs e)
{
    docViewer.FitToWidth();
}

If everything went according to plan, you should now be able to run your code and you should get a ScatterViewItem displaying your XPS file which is resizable, and which supports touch to navigate around the document.

(I think this should also work with the Surface Toolkit for Windows Touch, but I haven’t tried it yet)

Advertisements
About

I have been working in the world of technology for 25-odd years. I am an entrepreneur and consultant, focused on software solutions, social networking, and innovation processes. Currently, I am a Principal Consultant with T4G Limited, specializing in Portal Technologies (including SharePoint), software/systems development, service oriented architectures, and many other things which I will probably not remember until I need to use them. Prior to that, I was VP of Technology at Whitehill Technologies, Inc., where I spent almost 9 years helping to grow the company from a start-up to one of the most successful private software companies in Canada. Prior to that I worked on internet conferencing using early VoIP, and on large military communications projects. Before even that, I worked in satellite control, and remote sensing. Going way back to university, my focus was on theoretical physics and astrophysics. Currently my interests revolve around most aspects of software development, from technologies to management, and in the area of defining sustainable, repeatable processes for innovation within technology organizations. I also have a particular interest in Tablet PC technologies – I have been using one for several years, and I love it. On the personal side, I still have a strong interest in all aspects of science, especially physical sciences, as well as philosophy and comparative religion. In addition, I am into music, playing guitar (badly, I am sorry to say), and reading almost anything I can lay my hands on. I am also a member of the IEEE/IEEE Computer Society, and of the Association for Computing Machinery.

Tagged with: , , , , , , , , ,
Posted in Microsoft Surface, Software Development
6 comments on “Displaying an XPS Document on the Microsoft Surface
  1. thanks a lot for your article, it was very useful, and works on Surface 2.0 SDK too.
    In your case, can you scroll the document only touching the scrollbar, or you could
    scroll the document itself touching it, as in a default SurfaceScrollViewer?
    Because i cannot scroll the document touching it.
    thanks agagin.

  2. rr says:

    Thanks for this functionality just what I was looking for – I am running into one issue:
    The type reference cannot find a public type named ‘PresentationUIStyleResources’
    I added the folloing to my xaml file:
    xmlns:System_Windows_Documents=”clr-namespace:System.Windows.Documents;assembly=PresentationUI”
    but still complaining – Any ideas?

    Thanks

  3. Hey that’s pretty slick Fred. Nice work!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Obligatory Disclaimer
Please keep in mind that any opinions, points-of-view, comments, or other content which I post to this site are mine and mine alone. They in no way reflect the views of my employer, my country, my dog, my cat, or anyone else you can think of. To paraphrase Monty Python, "That is the theory that I have and which is mine, and what it is, too."

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 623 other followers

%d bloggers like this: