WPF Flow Documents and Images

Published: 2/28/2008
By: Brian Mains

Brian mains shows how to use the flow documents and images.

Introduction

The rendering model for WPF is quite unlike its predecessors in how it formats controls and other elements within a window. It also has a couple of options for how the contents of the window render. While it can work with fixed positioning, it can also work in a flow document form, meaning that documents can flow within the document area and adjust themselves when the window resizes in various ways.

Flow documents are a new feature of the Windows Presentation Framework (WPF), giving developers another option to display content. There are a variety of elements available that format the content in special ways, and this is a help too. You will recognize some similarities with HTML, in the ways it generates lists, tables, and the like. It also introduces other features like figures and floaters, which add to the appeal of the content design.

In addition, WPF changes the way that images are supported, and we'll touch upon that and how the framework takes an image path, and converts it to the correct object.

WPF Documents

Flow document content, as I mentioned before, is a new feature of WPF. In its simplest form, the following code creates a flow document reader with an empty document:

Listing 1: Flow Document Reader Content

There are three levels of flow document reader controls built-in to the framework: the FlowDocumentPageViewer, FlowDocumentScrollViewer, and FlowDocumentReader controls. FlowDocumentReader is the most functional, and therefore this article will use this control. Built into the control is a zoom control, a page layout control allowing you to choose the display format, and an in-built text searching control. Take a look at the example screenshot below:

Figure 1: A FlowDocumentReader Control Example

images/fig01.jpg

This control has the ability to reposition its content based on the size of the screen. If the content is larger, it may reposition the content into a multi-column format. See the alternative screenshot below:

Figure 2: A Resized Flow Document Reader With Multiple Columns

images/fig02.jpg

The flow document is made up of a variety of objects. Primarily, there are two types of elements: block and inline elements. A block element is an element that can have multiple inline elements. One of the more common block elements is the Paragraph class, which represents a paragraph of text. This can be used to represent text in a flow document. The following is the makeup of some text within the document:

Listing 2: Flow Document Content

What isn't exactly obvious is that the Paragraph element uses the Run element as its child. The Run element is optional and doesn't need to be declared (it's implicitly created); however, when working with paragraphs in code, you will need to instantiate an instance of the Run class, which will contain the paragraph text. The Paragraph element breaks out the text into paragraphs in a document as you could imagine.

Within flow documents, you can't embed WPF controls. However, using either the InlineUIContainer or BlockUIContainer allows a flow document to contain WPF controls, in inline or block fashion. The InlineUIContainer element can be used within a Paragraph or any other control that supports inline elements (because it is an inline element, it can be used as a child of the block element); the BlockUIContainer element can host any controls that can be used within a Section or any other control that supports block elements. Below is an example of the inline and block UI Container classes.

Listing 3: Block/Inline UI Containers

In addition, flow documents support a table structure, which looks similar to an HTML table with a few added steps. The following is an example table:

Listing 4: Tables in Flow Documents

The TableRowGroup element groups a series of table rows together, instead of being an element directly under the table. Also note the use of the paragraph element as a child of the TableCell element; the content must appear in the paragraph element. There is an interesting difference with the TableCell element approach; this is because the TableCell isn't a block or inline element (it doesn't inherit from those base classes); rather, it branches off from the root base class.

Also, if you want to change the sizing of the table, the Table object has a Columns collection, where you can specify widths for each column as such:

Listing 5: Table Column Setup

Similar to the Grid element, tables can have relative widths specified for them.

Flow documents also support list-based structures. Lists work very similar to HTML lists, but with more verbose setup, as such:

Listing 6: Lists in Flow Documents

The List has a MarkerStyle attribute that defines the type of list to render (an enumerated value).

I'm sure that if you've read computer books or other books, you've seen quotes on the sides of the page, as a way to stand out to the reader as they browse through the page in an effort to drive home a point. These can be achieved in flow documents, through the use of the Figure and Floater elements. Each has its own level of control, as to what it can do or can't do.

In order for the floater to stand out and appear in the portion of the page, you have to provide a manual Width value, and give it a HorizontalAlignment setting. The figure element allows more control over positioning than the floater, so it can allow a user to control how the figure appears in the page with more precision. For instance, the Floater element example puts the text on the right side, allowing the text to wrap around it:

Listing 7: Quote Listing on the Right of the Document

Images

At the core, an image is pretty easy to setup in XAML code. The following is an image control that displays a JPEG picture.

Listing 8: Basic Image Declaration

That is pretty simplistic. However, at its core, the Source property is something different than a string, that you would see in the ASP.NET Image control, for instance. Rather, it is an ImageSource object, which defines Height/Width properties. Some of the derivatives are the BitmapSource and the DrawingImage controls, which represent image metadata API for those object types. However, in the XAML markup, one can specify a string value. This is because the ImageSource class declares a TypeConverter attribute, and this class is responsible for converting the value in the designer. This class also declares a ValueSerializer attribute, which specifies a class responsible for serializing the object to a string value.

Conclusion

Flow documents have a lot of capabilities, with all of the inline elements that are supported. There are a variety of elements, very similar to HTML that provides a lot of functionality in WPF applications. As a sample, I've embedded portions of this article, and some added content, as a sample of flow documents. Resize the document and see how flexible flow documents can be.

Please visit the link at the below url for any additional user comments.

Original Url: http://dotnetslackers.com/articles/wpf/WPFFlowDocumentsAndImages.aspx