Book
The Book control is an ItemsControl
that presents the items as pages in a book.
Overview
The Book control can be used to recreate a real-world book, including support for page turn animations. The pages can be turned by clicking and/or dragging the corners from one side to the other, or programmatically using routed commands or public methods. Includes support for horizontal and vertical orientations and several other options.
All the items presented in a Book are wrapped in an instance of BookPage, just like a ListBox
wraps items with a ListBoxItem
.
Orientation
The Book control supports Horizontal
and Vertical
orientations. This parameter refers to the way the pages turn and is perpendicular to the spine of the Book.
The horizontal (left) and vertical (right) orientations of the Book
In both orientations shown above, the '1' page (left/top) is considered a Back
page, and the '2' page (right/bottom) is considered a Front
page. Each sheet of page has a front and a back. In the examples above, the sheet of paper on the right/bottom has '2' on the front and its back is not visible. If the sheet on the right/bottom was turned, then its back would be visible and its front would not.
Each BookPage has a Face property to indicate which side or face of the sheet it is on.
First Page Placement
The first page of a Book can either be on the front or back of the first sheet of paper. When oriented horizontally, this effectively determines whether the first page is on the left (back) or right (front) side of the book. The IsFirstPageFront property controls which side (Front
or Back
) the first page is placed on.
Populating the Book
A Book can be populated with content by adding content to the Items
collection, or by setting the ItemsSource
property. The ItemsSource
property can be data-bound to a collection, just like any other ItemsControl
. The Book can be populated with any type of object.
The Book control supports UI virtualization when the underlying items are not instances of BookPage. See the "Virtualization" section below for more information.
Applying a Custom DataTemplate
When the Book is populated with objects that are not instances of BookPage, a custom DataTemplate
is generally needed to properly present the data. The Book.ItemTemplate
property can be used to apply a custom DataTemplate
to all generated pages. Or, you can achieve more granular control using the by utilizing a BookPageTemplateSelector.
Alternatively, more granular control can be achieved using the Book.ItemTemplateSelector
property. This allows the DataTemplate
to be chosen dynamically based on the item being presented and it's associated BookPage. For convenience, BookPageTemplateSelector can be used to set the DataTemplate
for the first, last, back-facing, and front-facing pages.
Note
ItemTemplate
or ItemTemplateSelector
are only applied if the BookPage is an automatically generated container.
Applying a Custom Style
A custom look can be achieved by styling the Book and/or BookPage. This may include adding page accents, margins, rounded corners, etc.
A Book can be styled by setting the Style
property explicitly or using an implicit Style
.
One or more instances of BookPage can also be styled by setting the Style
properties explicitly or using an implicit Style
. The latter approach is automatically applied to all pages and makes styling a bit easier, as any new pages will automatically pick up the new style. One drawback to this approach, is that it doesn't allow the Style
to be selected based on whether the page is the first or last, or whether it's back or front facing.
The Book.ItemContainerStyle
property can be used to explicitly set the BookPage.Style
property for all the pages in a book. But this again, doesn't allow dynamic selection of the Style
based on the page's properties.
More granular control can be achieved using the Book.ItemContainerStyleSelector
property. This allows the page's Style
to be chosen dynamically based on the item being presented and it's associated BookPage. For convenience, BookPageStyleSelector can be used to set the Style
differently based on whether the page is the frist or last page, or whether it's back or front facing.
Note
ItemContainerStyle
and ItemContainerStyleSelector
are applied to all instances of BookPage in a book, regardless of whether they were automatically generated or not, and will override any implicit styles.
Turning Pages
Using the Mouse
There are two ways of turning the page with the mouse. The four outermost corners of the Book are hotspots
. You can either click in a hotspot to turn the page, or you can click and drag the corner to the opposite side of the Book. Clicking the hotspot will invoke an automated page flipping animation. Dragging the hotspot allows you to turn the page at your own pace. You can complete the page flip by releasing the drag on the opposite side of the Book or cancel the page flip by releasing the drag on the original side of the Book.
The HotspotExtent property allows you to specify the size of the hotspot. The property is of the Unit type, allowing plenty of flexibility in how you specify the size of the hotspot.
The hotpots of a Book control
Using the Keyboard
The Book control supports keyboard navigation. Here are the shortcuts that are supported by default:
Key(s) | Action |
---|---|
Home | First page |
End | Last page |
Right | Next page |
Left | Previous page |
Down | Next page |
Up | Previous page |
The Book control's keyboard navigation can be customized two ways. First, the ResetInputBindings member function can be completely overridden with custom input bindings. The base method can be optionally called, depending on whether the bindings are being customized or completely replaced. Second, the InputBindings
collection can be manually updated to remove or add specific items.
See the "Commands and Methods" section below for more information on the commands that are used by the Book control.
Tip
Events (discussed below) are fired in the same sequence when turning a page using the keyboard as when using the mouse, eventhough no page curl actually occurs. The page curl/flip can still be cancelled in the same way as with mouse navigation.
Commands and Methods
Pages can be programatically turned using several routed command or public methods. By default, support for the following NavigationCommands
commands is included:
FirstPage
GoToPage
LastPage
PreviousPage
NextPage
The following Book methods can also be used directly:
Events
PageCurlActivating
The PageCurlActivating event is fired when the mouse hovers over a hotspot. A handler of this event will receive a CancelBookPageRoutedEventArgs instance, which indicates the corner being curled and it's associated face. In addition, the Cancel property can be used to cancel the event.
Canceling the PageCurlActivating event prevents the page curl from occuring, therefore the end-user will not receive any visual feedback as to whether the mouse is hovering the hotspot.
PageCurlActivated
The PageCurlActivated event is fired when a page corner has curled. A handler of this event will receive a BookPageRoutedEventArgs instance, which indicates the corner being curled and it's associated face.
PageCurlDeactivated
The PageCurlDeactivated event is fired when a page corner has stopped being curled. A handler of this event will receive a BookPageRoutedEventArgs instance, which indicates the corner was previously curled and it's associated face.
PageFlipping
The PageFlipping event is fired when a page is about to flip. A handler of this event will receive a CancelBookPageRoutedEventArgs instance, which indicates the corner being curled and it's associated face. In addition, the Cancel property can be used to cancel the event.
Canceling the PageFlipping event prevents the page flip from occuring, therefore preventing the end-user from navigating away from a page.
SelectedViewChanged
The SelectedViewChanged event is fired when the selected view has changed. A pair of visible page faces is referred to as a view. A handler of this event will receive a PropertyChangedRoutedEventArgs<int>
instance, which indicates the old and new view indexes.
PageFlipped
The PageFlipped event is fired when a page has flipped. A handler of this event will receive a BookPageRoutedEventArgs instance, which indicates the corner being curled and it's associated face.
Virtualization
The Book control includes UI virtualization to allow a large number of pages to be presented. BookPage container objects are only realized for pages that are close to the selected view index. By minimizing the number of realized container objects at any given time, the Book control runs faster and uses less memory.
The number of pages that are realized at any given time is determined by the PageDepth property. This value indicates the number of pages realized on each side of the book. Typically with opaque pages, the default value can be left untouched. This value is only useful when using transparent pages, as pages that are not realized will not be visible.
Keep in mind that all pages on either side count towards the PageDepth. This includes opposing faces, which are not visible until the page is being turned, so these need to be accounted for.
Transparency
The BookPage.Background
can be set to a transparent or semi-transparent brush, thus making the page itself transparent/semi-transparent.
As mentioned in the "Virtualization" section above, the PageDepth property is very important when using pages with transparency. The pages behind the transparency need to be realized to avoid "popping" when the page is turned. In general, the PageDepth should be high enough to accomodate the largest number of consecutive transparent pages that will occur in the entire Book.