技术开发 频道

WPF使用流文档灵活地显示内容

    流文档基础知识

    至此您已了解了一些流文档的基础知识,接下来让我们回顾一下某些基础知识。如您所见,流文档是块的集合。在内部,所有块都是从 System.Windows.Documents.Block 类派生而来的 WPF 类。块又是从 ContentElement 派生而来(沿此链向上追寻几步),ContentElement 是 WPF 中专门为文档定义优化的一个相当低级别的类。此方法有些类似于您用来定义 WPF 界面的控件,它们都从 UIElement 派生而来。两者的继承树在概念上很相似,但并不完全相同。这意味着 WPF 控件和块不能直接组合。例如,一个按钮的标题不能设为一段文本,一个段落也不能直接包含一个按钮。这些控件和块之间存在一些细微差别,这是由于内容控件内的布局和块内的布局的运作方式截然不同这一事实所致。幸运的是,这两类 WPF 元素之间需要弥合的差异非常小。就按钮而言,它可以包含由带格式的文本构成的 TextBlock 对象;而块可以通过特殊 BlockUIContainer 块类包含任何 WPF 控件。这意味着,流文档可以包含所有类型的 WPF 元素(包括交互式用户界面、媒体和三维元素),而从另一个角度看,流文档也可是任何 WPF 用户界面的一部分,例如可以是控件内容的一个高级布局元素,也可以是一个真正的元素,例如销售点应用程序中的某一项的描述。

    可用块的列表理论上是可扩充的,因为开发人员可以派生他们自己的块类,然后创建他们自己的针对文档呈现引擎的增强功能。这提供了我所了解的任何其他文档呈现引擎都无法提供的自由度。但是,对一般的文档创建者公开的块数量通常有限。图4显示了最重要的块类型的列表。

图4 重要块类型
说明
段落 包含(潜在格式丰富的)文本
列表 包含各种不同类型(编号、项目符号等)的列表
包含与 Microsoft Word 或 HTML 中的表类似的表
BlockUIContainer 包含作为整个流的一部分的各种 UI 元素
包含一组其他块。段对于将常见属性应用于一组块中很方便,例如将同一字体属性应用于多个段落

    当使用 XAML 创建 WPF 流文档时,您事实上只要实例化某些类型。请看下面的 XAML 代码段(从此处起,我将省略命名空间定义,以让示例尽量简单):
<FlowDocument> <Paragraph>Hello World!</Paragraph> </FlowDocument>
    这会实例化一个 FlowDocument 类和 Paragraph 类(其文本设为“Hello World!”)。该段落被添加到 FlowDocument 的块集合中。请注意,对于所有 XAML 而言,元素名称都区分大小写,并且精确映射到作为 WPF 一部分而提供的类。您也可通过编程方式创建相同文档,如下所示:
FlowDocument doc = new FlowDocument(); Paragraph para = new Paragraph(); para.Inlines.Add(“Hello World!”); doc.Blocks.Add(para);
    当然,这远不及 XAML 提供的声明性方法那么直观,因此编程的方法只在特殊情形下采用。(当我需要创建一个格式丰富的报告,结果要更像一份真实的文档,而非通过许多报告引擎创建的表格形式的输出时,有时会使用此方法。)

    在许多情形下,段落本身带有格式丰富的内容,这也是通过实例化类实现的,如下所示:
<Paragraph>Hello <Bold>World!</Bold></Paragraph>
    在本例中,该段落包含两个文本段——“Hello”(使用默认格式)和“World!”(粗体)。这比较有趣,因为这表示此 XAML 不只是实例化一个段落,并将其文本设为一个简单的字符串;相反,它创建了含有两个子段的一个段落,每个子段包含不同格式的文本。在 WPF 中,这些段称为内嵌元素。就如一个流文档可以包含多个不同类型的块一样,段落也可以包含各种类型的内嵌元素。内嵌元素有多种变体。有些内嵌元素就是所谓的 Span,它们代表应用了特定格式选项的文本段。此例中的 Bold 元素是 Span 的一个特殊情形,其默认字体粗细设为粗体。内嵌元素的另一种类型是 Run,它是带有默认格式的文本段。因此,上面的 XAML 其实只是下例的简化:
<Paragraph> <Run>Hello </Run> <Bold>World!</Bold> </Paragraph>
    当然,它要方便得多,您不必使用 XAML 定义每个内嵌元素,但是如果您要以编程方式创建相同示例,了解内嵌元素的概念就非常重要了,因为它们不可以在代码中省略。以下是前面两个 XAML 示例的对等代码段:
Paragraph para = new Paragraph(); para.Inlines.Add(new Run(“Hello “)); Bold b = new Bold(); b.Inlines.Add(“World!”); para.Inlines.Add(b);
    Bold 是 Span 的特殊版本,其默认字体粗细设为粗体;Bold 类型由 Span 子类化而来,并且会覆盖 FontWeight 属性。类似特殊的 Span 还有 Italic 和 Underline。不过,这些特殊的 Span 并不是必不可少的,因为您也可以使用默认的 Span,并设置相应属性:
<Paragraph>Hello <Span FontWeight=”Bold”>World!</Span></Paragraph>
    当然,通过将某一文本段包到粗体或斜体标记中,来直接指定诸如粗体和斜体等属性的功能非常方便和直观,因此通常更多的是使用 <Bold>,而不是 <Span FontWeight="Bold">。不过,<Span> 元素还是非常有用的,因为有许多属性都要设为粗体以外的属性,而且那其中的大多数格式选项都没有单独的 Span 类型。事实上,许多非常常见的格式选项没有特殊的 Span。一个典型的示例就是设置字体。与 HTML 不同,流文档没有 <Font> 元素。相反,字体按如下方式设置:
<Paragraph>Hello <Span FontFamily=”Comic Sans MS” FontSize=”24”> World!</Span></Paragraph>
    诸如 FontFamily 等许多属性都可以始终在所有流文档类中找到。例如,若要设置一个完整段落而非只是一个内嵌元素的字体,您不使用 Span 即可做到:
<Paragraph FontFamily=”Comic Sans MS” FontSize=”24”>Hello World!</Paragraph>
    还有 Span 和 Run 之外的一些内嵌元素。下面就是其他一些更有趣的内嵌元素:

    Figure Figure 是有些不寻常的内嵌元素,因为它们包含块。因此,从某种意义上讲,Figure 几乎就像流文档内的迷你流文档。Figure 经常用于高级布局功能,例如段落中被普通文本流包围的图像。 
    Floater Floater 是轻型的图形。它们不支持任何图形放置选项,但是如果您需要的只是除标准段落对齐之外还能做些简单对齐的功能,Floater 会比较有用。
    LineBreak LineBreak 元素的作用与其名称所指的意义完全相同:它们会在段落内引入换行符。
    InlineUIContainer InlineUIContainer 是 BlockUIContainer 的内嵌元素等同项。如果您需要将任何类型的 WPF 控件与您其他的内嵌元素组合使用(例如让一个按钮在一个段落文本内移动),InlineUIContainer 正是您所需要的。
    Figure 始终用于流文档中(LineBreak 也是如此,不过它们几乎不需要详细讨论)。以下示例使用一个图形,将一个图像显示为一个更大流文档的一部分:
<Paragraph> <Figure Width=”200”> <BlockUIContainer> <Image Source=”Pictures\Humpback Whale.jpg” /> </BlockUIContainer> <Paragraph Foreground=”Blue” FontFamily=”Consolas”> The Whale</Paragraph> </Figure> The quick brown fox jumps over the lazy dog. The quick brown... </Paragraph>
    请注意,WPF 流文档中没有 Image 块。相反,图像以标准的 WPF Image 控件内嵌为 BlockUIContainer。(相同的方法也用于流文档内诸如视频或交互式三维模型等内容)。图 5 显示了与此类似的一个文档的呈现。



图 5 文本环绕图片和标题 (单击该图像获得较大视图)
0
相关文章