Customizing SinglePageViewer (Part 2)
posted 2005-10-12
In last episode, we constructed a minimal ControlTemplate for SinglePageViewer. Although it did not expose any UI, it was fully functional in terms of keyboard shortcuts, selection, and layout. Now we'll create a ControlTemplate with real UI. Here's the markup (it's long, but I'll break out the important parts):
<SinglePageViewer xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" MinZoom="50" MaxZoom="200" FontFamily="Candara, Verdana"> <SinglePageViewer.Template> <ControlTemplate TargetType="{x:Type SinglePageViewer}"> <AdornerDecorator> <Grid> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <Border Grid.ColumnSpan="3" Margin="5,5,5,10" Padding="5" BorderBrush="#aaa" BorderThickness="1,1,1,2" Background="#fff"> <Border.BitmapEffect> <DropShadowBitmapEffect /> </Border.BitmapEffect> <DocumentPageView DocumentViewerBase.IsMasterPage="True" PageNumber="0" /> </Border> <TextBlock Grid.ColumnSpan="3" Margin="0,0,0,20" VerticalAlignment="Bottom" HorizontalAlignment="Center" Text="{Binding Path=MasterPageNumber, RelativeSource=/TemplatedParent}" /> <Slider Grid.Column="1" Grid.Row="1" Margin="5,5,10,5" Value="{Binding Path=Zoom, RelativeSource=/TemplatedParent}" Minimum="{Binding Path=MinZoom, RelativeSource=/TemplatedParent}" Maximum="{Binding Path=MaxZoom, RelativeSource=/TemplatedParent}" TickFrequency="{Binding Path=ZoomIncrement, RelativeSource=/TemplatedParent}" /> <Button Grid.Column="0" Grid.Row="1" Command="PreviousPage" IsEnabled="{Binding Path=CanGoToPreviousPage, RelativeSource=/TemplatedParent}"> Previous Page </Button> <Button Grid.Row="1" Grid.Column="2" Command="NextPage" IsEnabled="{Binding Path=CanGoToNextPage, RelativeSource=/TemplatedParent}"> Next Page </Button> </Grid> </AdornerDecorator> </ControlTemplate> </SinglePageViewer.Template> <FlowDocument> <Paragraph FontSize="16"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur sodales, sem nec scelerisque aliquam, ipsum nibh tristique nisl, eu dictum ipsum neque nec dolor. Nullam magna lacus, mollis faucibus, auctor eget, placerat sit amet, odio. Morbi feugiat, ligula tristique condimentum luctus, eros nisi vestibulum ante, a porta dolor nibh sed nisl. Cras a libero vitae leo eleifend tristique. Fusce consequat, urna in consectetuer aliquet, felis purus luctus nisl, at sollicitudin sem augue quis ante. Fusce convallis nibh quis nisl. Fusce dictum faucibus velit. Proin tempus orci a leo. Integer suscipit. Vestibulum nisl libero, congue at, mollis sed, fringilla nec, lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec ac leo ut lectus tempus vestibulum. Proin vel enim eget nisi rhoncus mollis. Duis dolor mauris, dictum adipiscing, posuere nec, blandit et, orci. </Paragraph> </FlowDocument> </SinglePageViewer>
Here are a couple of screenshots of the markup, the first is zoomed out to a small font size, the second has a large font size:


We've changed the structure of our ControlTemplate a bit, and added some new elements. Here's a summary:
Border: In order ot make the content look like it's on a physical page, we've wrapped theDocumentPageViewwith aBorderelement.Borderis used to create a thin gray border and drop shadow (usingDropShadowBitmapEffect) around the content.TextBlock: This element displays the current page number. This is achieved by binding theTextpropertySinglePageViewer'sMasterPageNumberproperty.Slider: The horizontal slider is bound to theZoomproperty onSinglePageViewer.Button: We've created two buttons, for "Previous Page" and "Next Page." TheCommandproperty is set on the button, which hooks up theButtonto fire the appropriate command when clicked. We've also bound theIsEnabledproperty to disable the buttons when appropriate (e.g. the "Previous Page" button is disabled if we're displaying the first page).
Now we have a functional interface, but it's not particularly pleasing to the eye. In part 3, we'll create a more attractive look and feel.