#258 – RichTextBox Allows Richer Formatting than TextBox

The TextBox control allows you to set various properties to change the font used to display its text.  If you want to format only a subset of the text, or format text items separately, you need to use the RichTextBox control.

The RichTextBox control can only have one child element, which must be a FlowDocument.  The contained document is referenced by the Document property, which is the RichTextBox’s content property.

Here’s a simple example that compares a TextBox to a RichTextBox.

		<TextBox Text="This is a text box.." FontStyle="Italic" FontFamily="Cambria" FontSize="16"
			     Width="150" Height="50" Margin="10"/>

		<RichTextBox  Width="150" Height="75" Margin="10">
			<FlowDocument>
				<Paragraph>
					This is a <Bold>RichTextBox</Bold>, which allows formatting
					individual bits of text <Italic>separately</Italic>.
				</Paragraph>
			</FlowDocument>
		</RichTextBox>

#255 – Flow Text Around an Image in a FlowDocument

You can flow text around a user control in a FlowDocument using a Floater element.  One common use of a Floater is to flow text around an image.

You include a Floater as a child element of the Paragraph that contains the text that should flow around the image.  Below is a fragment of the content of a FlowDocument, which contains the Floater.

			<Paragraph>
				<Floater HorizontalAlignment="Left" Width="200">
					<BlockUIContainer>
						<Image Source="Twilight.jpg" />
					</BlockUIContainer>
				</Floater>
The said Eliza, John, and Georgiana etc. etc.
			</Paragraph>

#254 – Types of Containers for Hosting a FlowDocument

There are four different controls that you can use to host a FlowDocument:

  • FlowDocumentReader – Reader with support for multiple columns, paging, find and zooming
  • FlowDocumentPageViewer – Reader with support for multiple columns, paging and zooming
  • RichTextBox – Content displayed in an editable format
  • FlowDocumentScrollViewer – Content displayed  with a vertical scrollbar

Here are screenshots of each of the containers:

#253 – FlowDocument is Hosted in a FlowDocumentReader Automatically

Because FlowDocument does not derive from UIElement, you can’t include it in a Panel control.  You can use a FlowDocument as the main content in any ContentControl.  If you do this, the FlowDocument will automatically be hosted in a FlowDocumentReader.

The FlowDocumentReader displays some portion of a FlowDocument and provides controls to either page or scroll through the rest of the document.  It also supports displaying the document in multiple columns and provides an easy way to adjust the font size.

The image below shows a FlowDocumentReader hosting a FlowDocument.

The various widgets on the toolbar at the bottom are described below.

  • Find text within the document    
  • Navigate between pages  
  • Single Page / Double Page / Scrolling  
  • Zoom (make text larger)   

#252 – FlowDocument Flows its Content Automatically

A FlowDocument automatically flows its content to fit its current size.  In the example below, we include a FlowDocument in a FlowDocumentScrollViewer:

	<FlowDocumentScrollViewer>
		<FlowDocument FontFamily="Cambria" FontSize="14">
			<Paragraph>
There was no possibility of taking a walk that day.  We had been wandering, indeed, in the leafless shrubbery an hour in the morning; but since dinner (Mrs. Reed, when there was no company, dined early) the cold winter wind had brought with it clouds so sombre, and a rain so penetrating, that further out-door exercise was now out of the question.
			</Paragraph>
			<Paragraph>
I was glad of it: I never liked long walks, .. etc. etc.

At runtime, the content will flow/wrap to fit the current window:

Also note that the text is automatically justified–both the left and right sides of the paragraph are lined up.

#251 – Embedding an UIElement Within a FlowDocument

You can embed any UIElement into a FlowDocument using the BlockUIContainer block type.  This allows inserting controls into the middle of a document.  Note that since Panel derives from UIElement, you can embed not just single controls, but containers that host other controls.

Here’s an example.

	<FlowDocument FontFamily="Cambria" FontSize="14">
		<Paragraph>"Be who you are and say what you feel, because those who mind don't matter, and those who matter don't mind.
			— Dr. Seuss</Paragraph>
		<BlockUIContainer FontFamily="Arial" FontSize="12">
			<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
				<Button Content="Like it" Margin="10" Width="70" Height="25"/>
				<Button Content="Don't like it" Margin="10" Width="70" Height="25"/>
			</StackPanel>
		</BlockUIContainer>
		<Paragraph>We continue this document with some more lovely Dr. Seuss quotes..</Paragraph>
	</FlowDocument>

The document will look like this at runtime:

#250 – Including a Section Block in a FlowDocument

A Section is a type of Block that you can include in a FlowDocument.  A Section acts as a container for other blocks.  You can then set various properties on the block and have those properties apply to all elements within the block.

Here’s a short example:

	<FlowDocument FontFamily="Cambria" FontSize="14">
		<Paragraph>Act I - George and Martha return from a faculty party, but Martha soon informs George that she has invited over guests.</Paragraph>
		<Paragraph>Act II - The wives rejoin the men and Martha begins to describe her husband's only novel.</Paragraph>
		<Section Background="LightGreen" Margin="10" FontFamily="Arial" FontSize="12" FontStyle="Italic">
			<Paragraph>Novel is embarrassingly autobiographical.</Paragraph>
			<Paragraph>George speaks of Martha's hysterical pregnancy.</Paragraph>
		</Section>
	</FlowDocument>

#249 – Creating a Table in a FlowDocument

You can include a table in a FlowDocument as content by using the Table block.  You present your content by laying it out as rows and columns.

	<FlowDocument FontFamily="Cambria" FontSize="14">
		<Paragraph>Some Pixar films:</Paragraph>
		<Table>
			<Table.Columns>
				<TableColumn Width="50*"/>
				<TableColumn Width="15*"/>
				<TableColumn />
			</Table.Columns>

			<TableRowGroup Background="LightGray" FontWeight="Bold">
				<TableRow>
					<TableCell><Paragraph>Title</Paragraph></TableCell>
					<TableCell><Paragraph>Year</Paragraph></TableCell>
					<TableCell><Paragraph>Director</Paragraph></TableCell>
				</TableRow>
			</TableRowGroup>

			<TableRowGroup FontFamily="Verdana" FontSize="12">
				<TableRow>
					<TableCell><Paragraph>Toy Story</Paragraph></TableCell>
					<TableCell><Paragraph>1995</Paragraph></TableCell>
					<TableCell><Paragraph>John Lasseter</Paragraph></TableCell>
				</TableRow>
				<TableRow>
					<TableCell><Paragraph>Monster's, Inc.</Paragraph></TableCell>
					<TableCell><Paragraph>2001</Paragraph></TableCell>
					<TableCell><Paragraph>Pete Docter</Paragraph></TableCell>
				</TableRow>
				<TableRow>
					<TableCell><Paragraph>The Incredibles</Paragraph></TableCell>
					<TableCell><Paragraph>2004</Paragraph></TableCell>
					<TableCell><Paragraph>Brad Bird</Paragraph></TableCell>
				</TableRow>
			</TableRowGroup>
		</Table>
	</FlowDocument>

#248 – Creating a List in a FlowDocument

You can include lists of items in a FlowDocument using the List block.

	<FlowDocument FontFamily="Cambria" FontSize="14">
		<Paragraph>Some Pixar films:</Paragraph>
		<List>
			<ListItem>
				<Paragraph>Toy Story</Paragraph>
				<Paragraph FontStyle="Italic">I can have a 2nd paragraph.</Paragraph>
			</ListItem>
			<ListItem>
				<Paragraph>A Bug's Life</Paragraph>
				</ListItem>
			<ListItem>
				<Paragraph>Toy Story 2</Paragraph>
				</ListItem>
			<ListItem>
				<Paragraph>Monsters, Inc.</Paragraph>
			</ListItem>
		</List>
	</FlowDocument>

#247 – Types of Blocks that You Can Use in a FlowDocument

There are five different types of blocks that you can include in a FlowDocument.  A block can be one of the following:

  • Paragraph – A paragraph of text
  • List – A list of text items, typically displayed with a bullet character
  • Table – A table, with rows and columns
  • Section – A section of the document that can, in turn, contain other blocks
  • BlockUIContainer – A placeholder that allows inserting any UIElement into the document