轉載自:http://www.cnblogs.com/zlgcool/archive/2008/11/17/1335456.html
WPF面向的是UI展現,而文本顯示無疑是UI層中的重要功能之一。WPF提供了XPS (XML 文件規范) 和Flow Document (流文檔) 來在不同的場景下展現或者操作文檔的顯示。XPS(XML 文件規范)針對打印和面向頁面的內容,而”流文檔”則針對屏幕顯示以及提供更動態和可以論證的更復雜模型。“流文檔”幾乎適用於與文本內容相關的所有方面,從產品說明到整本書籍。
Flow Document是WPF3.0中提供的一個用於顯示的新功能,它給了開發人員另一種選擇去顯示內容。Flow Document通過類似 HTML 文檔的格式定義文本流,但其功能更強大,並可提供明顯更先進的布局選項。它內置了很多的元素,例如,Figure, Paragraph, Section, Floater, Table, InlineUIContainer等可以通過不同的布局和元素控制其顯示方式。並且,它支持對圖像的支持,使其可以像在HTML中一樣隨意控制。再加上其默認支持的導航,顯示模式,搜索,讓其內容展現方式有了進一步的提高。
Flow Document
Flow Document定義了這個流文檔的頂級顯示模式,在其內部可以包含諸如Section, Paragraph等標簽用來控制其層級顯示模式。這就類似於HTML中的DIV,TABLE等區域控制標簽一樣用來組成文檔的顯示結構。定義一個流文檔很簡單,你可以通過聲明一個Flow Document和其內部的顯示結構即可,例如以下代碼通過顯示了如何來創建了簡單的顯示功能。
| <Window x:Class="WpfFlowDocuments.Window2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Example Flow Document Content" Height="300" Width="600" HorizontalAlignment="Stretch"> <Window.Resources> <Style x:Key="TitleParagraph" TargetType="{x:Type Paragraph}"> <Setter Property="Paragraph.FontFamily" Value="Calibri" /> <Setter Property="Paragraph.FontSize" Value="14pt" /> <Setter Property="Paragraph.Background" Value="Brown" /> <Setter Property="Paragraph.Foreground" Value="White" /> <Setter Property="Paragraph.FontWeight" Value="Bold" /> <Setter Property="Paragraph.TextAlignment" Value="Left" /> </Style> <Style TargetType="{x:Type Paragraph}"> <Setter Property="Paragraph.FontFamily" Value="Calibri" /> <Setter Property="Paragraph.FontSize" Value="10pt" /> <Setter Property="Paragraph.Foreground" Value="Black" /> </Style> </Window.Resources>
<FlowDocument> <Section> <Paragraph Style="{StaticResource TitleParagraph}"> <Bold>Best Small Businesses to Start</Bold> </Paragraph> <Paragraph> <Underline>Learn from the examples of entrepreneurs who’ve succeeded in these hot start-up areas</Underline> </Paragraph> </Section> <Section> <Paragraph Background="LightYellow"> By Matthew Bandyk Posted November 13, 2008 </Paragraph> </Section> </FlowDocument> </Window> |
下圖顯示了XAML的效果。這里僅僅顯示了3個Paragraph並以設置了簡單的樣式,但沒有高級布局設置。Flow Document以默認的Page Viewer方式展示。
Figure 1: 普通聲明的Flow Document以Page Viewer的方式展示
顯示模式
Flow Document默認支持三種展現方式,這也對應了上圖中右下方的三個按鈕。默認的Flow Document會以FlowDocumentReader來生成。對於不同的展現方式,其包含的導航,搜索等都有所不同,甚至缺少某些功能。
· FlowDocumentPageViewer :以單獨的頁面顯示流文檔
· FlowDocumentScrollViewer:以連續的流顯示文檔,通過滾動條導航
· FlowDocumentReader :組合了滾動查看器和頁面查看器,讓用戶可以在兩種方法之間切換。這是用於流文檔的默認選項。
FlowDocumentPageViewer
此選項以單獨的頁面顯示流文檔,讓頁面翻轉而非滾動。這與 Word 中的“閱讀版式”類似。以下XAML片段聲明了文章以FlowDocumentPageViewer的方式顯示。
| <FlowDocumentPageViewer BorderThickness="1" BorderBrush="Blue" > <FlowDocument> <Section> <Paragraph Style="{StaticResource TitleParagraph}"> <Bold>Best Small Businesses to Start</Bold> </Paragraph> <Paragraph> <Underline>Learn from the examples of entrepreneurs who’ve succeeded in these hot start-up areas</Underline> </Paragraph> </Section> <Section> <Paragraph Background="LightYellow"> By Matthew Bandyk Posted November 13, 2008 </Paragraph> </Section> …… </Section> </FlowDocument> </FlowDocumentPageViewer> |
FlowDocumentPageViewer將提供以翻頁的方式來導航內容頁。通過你調整窗口的大小,流文檔會根據內容的位置、尺寸來調整流的布局(這就是你為什么會在變化窗口大小的時候看到多列的原因,流的布局變化)。

Figure 2: 以FlowDocumentPageViewer方式展現流文檔
FlowDocumentPageViewer提供默認的分頁導航和ZOOM功能,它提供的Find功能默認為隱藏,可以通過ApplicationCommands.Find命令或Ctrl + F來喚醒Find功能。
FlowDocumentScrollViewer
使用一個滾動條以連續的流顯示文檔,類似網頁或 Microsoft Word 中的”Web 版式”。ScrollViewer模式僅僅是以連續的方式顯示流文檔的內容,所以其不具備PageViewer的可以自動變化流布局的高級功能。在調整窗口大小時,流文檔無法以多頁或多列的方式顯示。
FlowDocuemntScrollViewer與FlowDocumentPageViewer的用法一模一樣,只需要將其關鍵字替換即可,如:
| <FlowDocumentScrollViewerBorderThickness="1" BorderBrush="Blue" > …… </FlowDocumentScrollViewer> |

Figure 3: 以FlowDocuemntScrollViewer方式展現流文檔
文檔展現視圖默認不具有Find欄和ZOOM欄,通過Ctrl + F調用。
FlowDocumentReader
此控件組合了滾動查看器和頁面查看器,讓用戶可以在兩種方法之間切換。這是用於流文檔的默認控件,而且對於以顯示復雜文本為特色的應用程序通常是一個不錯的選擇。除了將標記用FlowDocumentReader替換前邊的兩個標記中任何一個,便可以輕松使用這種高級的展現。
| <FlowDocumentReaderBorderThickness="1" BorderBrush="Blue" > …… </ FlowDocumentReader> |
注意展現視圖中出現了三個展現方式切換的按鈕。FlowDocumentReader具有一個名為ViewMode的屬性,可取的值為Page, TwoPage和Scroll,通過設置ViewMode可以在設定其初始展現方式。默認為Page,對應於FlowDocumentPageViewer。

Figure 4: 以FlowDocuemnReader方式展現流文檔
FlowDocumentReader 控件采取多列的方法呈現文本。這是另一項非常重要的可讀性功能,因為人們不喜歡讀跨越整個寬屏顯示頁面寬度的一行行文字。實際列寬因各種因素會有所不同, 例如用於內容顯示的可用總寬度、縮放系數和定義的列寬等。流文檔的默認列寬為字體大小的 20 倍,默認字體大小約為 300 個與設備無關的像素(3 1/8 英寸的精確尺寸顯示)。所以在你調整窗口大小時,一旦窗口寬度可以容納兩個默認列寬,流布局會自動更改為2列顯示。但是你可以通過設置ColumnWidth屬性來設置你自己的列寬度。
| <FlowDocumentReader BorderThickness="1" BorderBrush="Blue"> <!--<FlowDocumentScrollViewer BorderThickness="1" BorderBrush="Blue">--> <!--<FlowDocumentPageViewer BorderThickness="1" BorderBrush="Blue" >--> <FlowDocument ColumnWidth="500"> <!-- IsColumnWidthFlexible="False">--> <Section> <Paragraph Style="{StaticResource TitleParagraph}"> <Bold>Best Small Businesses to Start</Bold> </Paragraph> <Paragraph> <Underline>Learn from the examples of entrepreneurs who’ve succeeded in these hot start-up areas</Underline> </Paragraph> </Section> ……. </FlowDocument> </FlowDocumentPageViewer> |
默認情況下IsColumnWidthFlexible屬性是為true的,這表明在允許范圍內(像當前FlowDocument的整體寬度大於ColumnWidth或默認ColumnWidth寬度的整數倍時),將會增大ColumnWidth,這樣會讓整個布局會更規律和整齊。但你也可以通過設置它為False來強制列寬必須為你指定的寬度,這樣在其余的寬度將會保持空白。
通過設置ColumnGap等參數還可以來調整各個列之間的樣式。以下代碼片段設置了各個列之間的縫隙寬度(ColumnGap)和線條樣式。
| <FlowDocument ColumnRuleBrush="Gray" ColumnRuleWidth="5" ColumnGap="30"> <Section> <Paragraph Style="{StaticResource TitleParagraph}"> <Bold>Best Small Businesses to Start</Bold> </Paragraph> <Paragraph> <Underline>Learn from the examples of entrepreneurs who’ve succeeded in these hot start-up areas</Underline> </Paragraph> </Section> ……… </FlowDocument> </FlowDocumentPageViewer> |

Figure 5: 通過FlowDocument的屬性控制展現
Block嵌套
Flow Document是Block的集合,所有Block都是從 System.Windows.Documents.Block。Block又是從 ContentElement 派生而來,ContentElement 是 WPF 中專門為文檔定義優化的一個相當低級別的類。這類似於用來定義 WPF 界面的控件--它們都從 UIElement 派生而來。兩者的繼承樹在概念上很相似,但並不完全相同。這意味着 WPF 控件和塊不能直接組合。例如Paragraph中不能直接包含對類似Button的定義,但它可以通過特殊 BlockUIContainer 塊類包含任何 WPF 控件。這意味着,流文檔可以包含所有類型的 WPF 元素(包括交互式用戶界面、媒體和三維元素),而從另一個角度看,流文檔也可是任何 WPF 用戶界面的一部分,例如可以是控件內容的一個高級布局元素,也可以是一個真正的元素。
展現圖像Figure
Figure標記我們通常可以用來展現圖像。可以根據設置HorizontalAnchor屬性和VerticalAnchor屬性的值,流布局會根據其空間布局而改變。這很有助於我們用各種不同的方式來展現圖線及其文字的布局。你可以讓文字環繞圖像,也可以讓文字像HTML中的Float一樣,這顯得很簡單。下邊的代碼片段將圖像顯示在Content的中央:
| <Paragraph> <Figure Width="120px" HorizontalAnchor="ContentCenter" VerticalAnchor="ContentCenter" BorderBrush="Gray" BorderThickness="1"> <BlockUIContainer> <Image Source="09.jpg" Height="120px" Width="100px" Margin="0" /> </BlockUIContainer> <Paragraph Foreground="Blue"> Figure - Model Car</Paragraph> </Figure> America's economic future is uncertain. Unemployment is up sharply. Credit is tight. People are worried about their savings. So is it a great time to start a business? "Are you crazy?" might be the quick answer. </Paragraph> |
當然,Figure還有一個重要的用戶就是設置標題。對於標題,你可以通過設置Width為1Content或者nColumn等方式來表示其所在布局中的位置。以下代碼片段設置了如何定義一個跨越整個文檔所有列的標題:
| <Paragraph> <Figure HorizontalAnchor="PageCenter" VerticalAnchor="ContentTop" Width="1Content" Background="Brown"> <Paragraph Foreground="White" FontSize="18"> <Bold>Best Small Businesses to Start</Bold> </Paragraph> <Paragraph> <Italic>Learn from the examples of entrepreneurs who’ve succeeded in these hot start-up areas</Italic> </Paragraph>
<Paragraph Foreground="Blue"> By Matthew Bandyk </Paragraph> <Paragraph Foreground="Blue"> Posted November 13, 2008 </Paragraph> </Figure> </Paragraph> |
展示一下最終的結果吧。看起來很酷,不是嗎?也很容易哦。

Figure 6: 通過Figure標簽來定制標題和圖像
Float標記
Float標記類似於CSS中的Float屬性,它定義了標簽內的內容以浮動的方式顯示。就像在CSS中的解釋一樣,它打破當前的流布局,以特定的方式來重新布局內容。HorizontalAlignment 屬性和Width屬性可以控制其展現方式。
| <Paragraph> The demand for energy efficiency and an environmentally friendly footprint is also spurring entrepreneurship. Energy auditors help businesses and homes save money by reducing energy costs. <Floater HorizontalAlignment="Right" Style="{StaticResource FloatingContent}"> <Paragraph>Retirement Widget</Paragraph> <Paragraph>Search on Google</Paragraph> </Floater> </Paragraph> |

Figure 7: Float標簽以浮動方式重新布局
InlineUIContainer和BlockUIContainer
InlineUIContainer 和 BlockUIContainer 提供了可以在Flow Document中插入WPF控件的能力。InlineUIContainer 可以被聲明在像Paragraph等支持inline元素的對象中來Host任意的WPF控件,而BlockUIContainer可以被聲明在像Section等支持block元素的對象中。他們都可以host任意的WPF控件。
| <Section> <Paragraph> This contains some text and <InlineUIContainer> <Button>Button Control</Button> </InlineUIContainer> interspersed. </Paragraph> <Section> <BlockUIContainer> <Button>Host In Block Control</Button> </BlockUIContainer> </Section> </Section> |
其他標記
類似於Html中我們經常也會用到以下幾中元素:
· Table元素 : 允許內容以表格的方式展現。
| <Table BorderBrush="Black" BorderThickness="1"> <Table.Columns> <TableColumn Width="*"></TableColumn> <TableColumn Width="2*"></TableColumn> </Table.Columns> <TableRowGroup> <TableRow> <TableCell> <Paragraph>Type tile here</Paragraph> </TableCell> <TableCell> <Paragraph>Row Content Display Area</Paragraph> </TableCell> </TableRow> <TableRow> <TableCell> <Paragraph>Type tile here</Paragraph> </TableCell> <TableCell> <Paragraph>Row Content Display Area</Paragraph> </TableCell> </TableRow> </TableRowGroup> </Table> |
· ListItem元素:以列表的方式展現內容。通過MarkStyle可以改變其列表風格。
| <List MarkerStyle="Decimal"> <ListItem> <Paragraph>this area shows as list item</Paragraph> </ListItem> <ListItem> <Paragraph>this area shows as list item</Paragraph> </ListItem> <ListItem> <Paragraph>this area shows as list item</Paragraph> </ListItem> <ListItem> <Paragraph>this area shows as list item</Paragraph> </ListItem> </List> |
· LineBreak:添加一個換行標記。

Figure 8: 在Flow Document中應用Table, ListItem和Floater.
Flow Document提供了一系列的默認導航、分頁、搜索功能,並可以通過以類似HTML的方式展現內容。更為客觀的是,由於支持內嵌WPF Control,我們可以提供更多的可控功能。
附加示例代碼:下載
