技术开发 频道

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

    显示流文档

    您可能已经注意到,每当显示流文档时(无论是在浏览器中还是在 XamlPad 中),显示的似乎不只是文档本身,还会显示其他少量内容。特别是,文档底部会呈现一些控件。如图 8 所示,流文档默认会通过 FlowDocumentReader 控件呈现,它提供了一组标准功能,例如缩放、分页、不同视图模式切换,甚至查找功能。事实上,流文档需要由一些能够显示它们的某类控件承载。流文档的默认查看器是 FlowDocumentReader 控件,除非您明确使用其他控件,否则该控件会自动实例化。WPF 目前提供三个不同的控件用于查看流文档:



图 8 FlowDocumentReader 控件中的控件按钮 (单击该图像获得较大视图)
    FlowDocumentScrollViewer 此控件使用一个滚动条以连续的流显示文档,类似网页或 Microsoft Word 中的“Web 版式”。图 9 显示的是滚动查看器中的文档。



图 9 使用 FlowDocumentScrollViewer 控件 (单击该图像获得较大视图)
    FlowDocumentPageViewer 此控件以单独的页面显示流文档,让页面翻转而非滚动。这与 Word 中的“阅读版式”类似。图 10 显示的是页面查看器。在这里,图 9 中的文档使用 FlowDocumentPageViewer 控件呈现,滚动条被分页机制取代。这种简单的流布局方法已被一种更高级、多列的分页布局所取代。


图 10 使用 FlowDocumentPageViewer 控件 (单击该图像获得较大视图)
    FlowDocumentReader 此控件组合了滚动查看器和页面查看器,让用户可以在两种方法之间切换。这是用于流文档的默认控件,而且对于以显示复杂文本为特色的应用程序通常是一个不错的选择。在图 11 中,图 9 和图 10 中显示的同一文档通过 FlowDocumentReader 呈现,它将滚动查看器和页面查看器两种方法结合在一起。此外,它还启用了其他控件中默认隐藏的搜索功能(其他查看器的确支持查找功能,通过执行 ApplicationCommands.Find 命令或从键盘上按 Ctrl+F 可实现该功能)。读取器控件还支持多页视图,这稍微改变了基于页面的呈现,以及列和图的呈现方式。


图 11 使用 FlowDocumentReader 控件 (单击该图像获得较大视图)
    虽然 FlowDocumentReader 几乎对所有基本使用情形都很有吸引力,但选择怎样的控件还需视您的情况而定。它用途广泛且功能强大,并支持分页布局,这在许多情形下是比滚动更高级的功能。关于该主题的更详细讨论不在本文探讨范围之内,但事实证明,滚动及重合等相关效果是人们较之数字化文本更喜欢打印文本的主要原因之一。分页方法在许多情况下更为自然,有助于让数字化阅读被更普遍接受。

    那么您如何定义要使用哪个控件呢?一个简单但相当强力的方法是将想要的控件添加到文档的 XAML 中:
<FlowDocumentScrollViewer xmlns=’http://schemas.microsoft.com/winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’> <FlowDocument> <Paragraph>The quick <Bold>brown fox</Bold> jumps over the lazy dog.</Paragraph> </FlowDocument> </FlowDocumentScrollViewer>
    在本例中,文档根已被设为一个 FlowDocumentScrollViewer 标记。也就是说,您不再只是定义一个单纯的文档而已。相反,您在定义一个完整的 XAML 界面,而它碰巧使用滚动查看器作为其根。滚动查看器的内容是最开始示例中的流文档。(请注意,命名空间定义现在使用滚动查看器标记,而非流文档标记)。图 9 到图 11 是使用此方法创建的,不同的查看器控件用作根元素。

    我为何把这称为强力方法呢?这是因为,从结构角度看,将用户界面定义与其实际数据相混合会导致一些问题。而更理想的状况是将文档与其界面分开。将读取器与文档混合在一起有点像创建一个 SQL Server™ 表,并出于某种原因定义该表只能在 Windows Forms DataGrid 中显示。有若干方法可让文档与 UI 定义分离。如果想使用上文所示的 ASP.NET 方法将流文档作为 Web 应用程序的一部分显示,您可使用所需的查看器控件定义 ASP.NET 页面,然后只要使用标准 ASP.NET 代码合并到实际内容(单独存储,可能在数据库中)即可。

    另一方面,在一个典型的 WPF 应用程序中,您可以只要使用标准 WPF、Windows 和 XAML 浏览器应用程序 (XBAP) 方法来定义您的用户界面,然后动态加载您的文档即可。图 12 显示的是使用我文章中的一个虚构库的一个简单示例,这些文章显示在左上角的一个列表框中。用户从列表中选择一篇文章时,该文档会自动加载到占用大部分窗体的 Flow Document Reader 控件。请注意,诸如 alpha 值混合处理等标准 WPF 技术在此设置中也能使用。您会注意到,实际的流文档是半透明的,背景中我的照片也在闪烁。另外也请注意,应用程序使用了一个列表框、图像,一个标签和一个 FlowDocumentReader 控件来创建虚构文章的库。



    图 12 使用列表框、图像、标签和 FlowDocumentReader 控件 (单击该图像获得较大视图)
这个例子最棘手的地方是将实际文档加载到查看器控件中。这通过 System.Windows.Markup.XamlReader 类实现,它允许动态加载任何 XAML 内容,包括但不限于流文档。以下是我绑定到列表框选定更改事件的一行代码:
documentReader.Document = (FlowDocument)XamlReader.Load( File.OpenRead(fileName));
    Load 方法会返回一个对象,因为 XAML 文件中的根元素可以代表许多不同类型。在我的例子中,我知道返回值为 FlowDocument,因此我只要执行一个转换,并将该文档指定给 FlowDocumentReader 控件的 Document 属性即可(此例中,我将控件实例命名为 documentReader)。请记住,这只是个例子。生产品质的代码此处当然还需要一些错误处理。

    请注意,您了解的关于 WPF 的所有东西都适用于本例。例如,读取器控件只是支持样式的标准 WPF 控件。也就是说,您可以完全更改所有 UI 元素的外观,例如缩放栏、视图模式切换或分页控件。(您的控制能力受到限制的唯一元素是搜索框,虽然如果您不喜欢它,就根本不必用它。)

    此外,我的例子显示的是基于 Windows 的应用程序,相同的应用程序也可以作为 XBAP 部署,并在 Web 浏览器内运行(当然,我们还是假设用户已安装了 .NET Framework 3.0)。请注意,Microsoft Silverlight™(原代号为“WPF/E”)是不够的,因为 Silverlight 只支持 WPF 的子集,且并不支持流文档。
0
相关文章