1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Windows Presentation Foundation 巡游

Windows Presentation Foundation 巡游

时间:2019-07-29 06:13:24

相关推荐

Windows Presentation Foundation 巡游

发布日期: 11/10/ | 更新日期: 11/10/

Tim Sneath

Microsoft Corporation

适用于:

WinFX Runtime Components September CTP(PDC 版本)

摘要:纵览 Windows Presentation Foundation(以前代号为“Avalon”)以及这一新图形子系统的背景。对该版本中可供开发人员使用的体系结构和主要组件进行研究。

下载 WinFX Runtime Components September CTP September(PDC 版本)。

下载相关的示例代码:WPF_PDC_Samples.msi。

本页内容

简介

在过去十年中,我们看到了应用程序开发模型形成了两个分支 — 传统的“智能客户端”安装应用程序和基于 Web 的应用程序,两者都为了在开发界内占据统治地位而展开竞争。这两个模型都要求开发人员牺牲在另一个模型中被视为理所当然的功能。Web 应用程序提供了更大的作用范围、更简单的部署和简易性,以弥补状态的丢失、更为复杂的开发模型以及集成度较低的平台体验(尽管最近重新发现了诸如 AJAX 这样的技术)等缺点。另一方面,Windows 领域使人们开发的应用程序有希望脱机工作并充分利用客户端硬件,但丧失了部署的简易性以及可用于 Web 应用程序的无数种标记工具支持。能够提供独立的、基于浏览器的应用程序、简易的部署、出色的工具支持和深度平台集成的客户端应用程序模型具有明显的作用。

自从在 Windows 的第一个版本中首次出现以来,构成 Windows 用户体验核心的图形子系统(USER32 和 GDI 库)实际上已经诞生了将近二十年。当然,随着时间的推移,USER32 和 GDI 经历了重大的演变和发展,并且在所有领域都引入了很多新的服务和功能。 同时,还出现了诸如 Direct3D 这样的新呈现技术,这些技术能够充分利用在最新的视频卡中公开的图形功能。但是,目前的大多数主流应用程序都没有提供这些图形卡实现的体验。

返回页首

Windows Presentation Foundation

Windows Presentation Foundation(以前称为“Avalon”)是 Windows 中新的关键图形子系统,它为用户界面、2D 和 3D 图形、文档和媒体提供了统一的方法。它在 .NET Framework 基础上生成,并利用 Direct3D 进行基于向量的呈现,为生成所有种类的浸入式应用程序提供了强大的解决方案。另外,Windows Presentation Foundation 通过提供声明性编程模型来实现“工具性”和灵活性,从而使设计人员成为开发过程不可分割的组成部分。

可按照如下方式对 Windows Presentation Foundation 背后的设计原则进行分类:

图1 显示的体系结构关系图标识 Windows Presentation Foundation 的主要组件。(请注意,方框的大小不代表各个组件的相对大小或重要性。)

1. Windows Presentation Foundation体系结构

在顶层,Presentation Framework 提供了一个托管 API,它提供对基础功能的完全访问。绝大多数 Windows Presentation Foundation 开发人员都将专门使用这一层。该框架包含大量标准控件(如 Button、Label、Menu);布局面板;2D 和 3D 图形和文本基元;对图像处理效果、媒体、动画和文档服务的支持;以及对与 GDI、DirectX 和 Windows 窗体/GDI+ 之间的互操作性的支持。

Windows Presentation Foundation 的真正主力是可视系统。Windows Presentation Foundation 中的大多数元素都派生自一个 Visual 基类。可视系统组合所有数据并产生屏幕输出。我们就是在这里将视频和音频、2D、3D 和动画集成在一起,并提供某些文本布局服务。位于该体系结构模型较低位置的是组合引擎,它负责在屏幕中呈现一个可视化树,并考虑从透明层到窗口区域无效的所有方面。

Windows Presentation Foundation 中的所有呈现操作均通过 Direct3D 完成(实际上,Windows Vista 硬件徽标程序需要 DirectX 9 的 GPU)。通过将更多的图形处理操作移动到 GPU 中,我们可以让 CPU 有能力完成其他工作,从而提高性能,同时改善图形的质量。然而,这些优点并不局限于 3D 领域 — 2D 图形也利用了相同的服务;Windows Presentation Foundation 内部未使用 GDI(除非与旧式元素集成)。对于安装有 Windows Vista 的计算机而言,新的显示驱动程序模型提供了优质的输出,从而使媒体密集型应用程序获得较高的性能。

返回页首

布局:将元素放到屏幕上

布局是任何用户界面子系统的基础服务之一,它涉及如何确定元素在窗口中的位置。设计 Windows Presentation Foundation 布局系统的目的是为灵活的可扩展模型提供支持,该模型针对内容进行优化,并且能够正确地处理数据、样式和控件。

传统的应用程序平台(如 Win32)几乎没有布局的概念:控件放置在画布上的 (x,y) 坐标系中,并且开发人员需要手动提供对确定任何元素的原点和尺寸的支持(考虑窗口大小调整和显示器 DPI 设置)。另一方面,Windows Presentation Foundation 提供多种适合于内容并且在窗口内管理控件和项目位置的布局实现。

在 Windows Presentation Foundation 中,几乎可以使用任何元素作为其他元素的宿主。例如,Button 可按如下方式包含图像:

<Window xmlns="/winfx/avalon/" ><Button Width="260" Height="200" ><Image Source="C:/WINDOWS/Web/Wallpaper/follow.jpg" /></Button></Window>

此外,Windows Presentation Foundation 提供五个布局面板,以便控制和约束子元素的大小和位置:Canvas、DockPanel、StackPanel Grid 和 WrapPanel。

SDK 包含一个用于试验 XAML 的出色工具,叫做 XamlPad。XamlPad 为编辑的代码提供基本的错误报告和 WYSIWYG 预览窗口。

布局面板

Canvas使您可以进行 (x,y) 定位,这与 GDI 和 GDI+ 目前提供的功能类似。您还可以使用附加的属性来控制项的位置。例如:

<Border xmlns="/winfx/avalon/"><Canvas Background="silver" Margin="20" LayoutTransform="scale 2"><Button Canvas.Top="30" Canvas.Left="50">Hello world!</Button></Canvas></Border>

这里,Canvas.Top 和 Canvas.Left 是 Canvas 类中的属性,应用于 Button 以控制其位置。LayoutTransform 属性(它是用来派生所有较高级别类的 FrameworkElement 类的一部分)按照 3.0x 幅度缩放输出。

DockPanel使您在停靠项时无需担心它们的确切 (x,y) 位置:

<Border xmlns="/winfx/avalon/"><DockPanel Background="silver" Margin="20" LayoutTransform="scale 2"><Menu DockPanel.Dock="Top"><MenuItem Header="File" /><MenuItem Header="Edit" /></Menu><TreeView><TreeViewItem Header="root1"><TreeViewItem Header="child" /></TreeViewItem><TreeViewItem Header="root2"></TreeView><ListBox><ListBoxItem>listBoxItem1</ListBoxItem><ListBoxItem>listBoxItem2</ListBoxItem></ListBox></DockPanel></Border>

StackPanel提供一个从左至右或从上至下放置内容的堆栈模型。

<Border xmlns="/winfx/avalon/"><StackPanel Orientation="Horizontal" Background="silver" Margin="20" LayoutTransform="scale 2"><Button Height="30" Margin="5">OK</Button><Button Height="30">Cancel</Button></StackPanel></Border>

Grid提供一个允许进行行/网格定位的模型:

<Border xmlns="/winfx/avalon/"><Grid Background="silver" Margin="20" LayoutTransform="scale 3"><Button Width="200" Height="60" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="20" >Hello</Button></Grid></Border>

在网格中,可设置列和行定义,从而可以设置宽和高。可将上述项设置为绝对值(x 像素宽),或者在考虑绝对大小调整之后使用星号表示法来分配剩余的空间。还可以设置一个系数来确定分配该空间的方式。例如:

<Border xmlns="/winfx/avalon/"><Grid LayoutTransform="scale 3" ShowGridLines="true"><ColumnDefinition Width="30" /><ColumnDefinition Width="2*" /><ColumnDefinition Width="*" /><RowDefinition /><Button Grid.Column="1" Margin="10">Hello world!</Button></Grid></Border>

可用 SharedSizeGroup 属性为多个对象指定共享的大小。例如,可使用该属性来指定两个按钮具有相同的宽度(即使它们通常具有不同的大小范围)。例如:

<Border xmlns="/winfx/avalon/"><Grid LayoutTransform="scale 2" ShowGridLines="true" IsSharedSizeScope="true" Height="80"><ColumnDefinition Width="30" /><ColumnDefinition Width="Auto" SharedSizeGroup="Buttons" /><ColumnDefinition Width="Auto" SharedSizeGroup="Buttons" /><RowDefinition /><Button Grid.Column="1" Margin="10">OK</Button><Button Grid.Column="2" Margin="10">A very long cancel button</Button></Grid></Border>

WrapPanel模型是资源管理器窗口的右侧窗格,使您可以处理在当前行已满之后流入新行中的项。例如:

<Border xmlns="/winfx/avalon/" LayoutTransform="scale 2"><WrapPanel Background="Silver" Margin="10"><Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /> <Button /></WrapPanel></Border>

面板负责其子元素的布局。它们定义内容的大小和形状、对齐方式和边距。面板的子元素可以是诸如 TextBox 或 Button 这样的元素,也可以是另一个面板。例如,DockPanel 可以包含 StackPanel。

项调整大小以适应它们所包含的内容 — 这是一个重要的概念,因为它确保了应用程序的本地化不需要重新校准应用程序布局(因为不同语言的同一句子 — 例如“Auf Wiedersehen”与“Goodbye”— 具有不同的文本长度)。可用 HorizontalAlignment/VerticalAlignment 属性应用对齐方式,并且使用 Margin 属性指定边距。

ScrollViewer提供子元素内容的滚动视图;如果内容溢出可用的空间,则会显示一个滚动条并允许用户在内容区域周围移动。例如:

<Border xmlns="/winfx/avalon/" LayoutTransform="scale 2"><ScrollViewer><TextBlock FontSize="20" TextWrapping="Wrap" FontFamily="Global User Interface">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce posuere volutpat erat. Praesent imperdiet nibh nec pede. Mauris quis orci. Maecenas luctus, risus tempus dapibus mollis, magna metus convallis nunc, eget pulvinar eros ipsum consectetuer dui. </TextBlock></ScrollViewer></Border>

ViewBox具有约束内容的大小以适应父面板的相反效果。这就提供了一种自动缩放效果。

<Border xmlns="/winfx/avalon/"><Viewbox><TextBlock FontFamily="Global User Interface">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</TextBlock></Viewbox></Border>

布局协议是一个递归过程,它是某种形式的协商,目的是确保所有元素都基于其请求获得“公平”数量的空间。首先,将发生一个测量过程,其中,父元素询问子元素希望自己多大,而子元素用 DesiredSize 进行响应。然后,将发生排列过程,其中,父元素以 ActualSize 属性的形式告诉子元素它将有多大。在进行计算时,特殊值 Double.PositiveInfinity 意味着“适合于内容”。可通过重写面板的 MeasureOverride 和 ArrangeOverride 元素来处理这一问题。

返回页首

XAML

在继续详细考察图形功能之前,让我们花一点儿时间来讨论 Windows Presentation Foundation 中 XAML 的使用。您已经看到迄今为止的所有示例都使用 XAML。但重要的是,您需要知道 XAML 只是编写 UI 代码的便利方式,而不是 Windows Presentation Foundation 必不可少的组件。可以用 XAML 完成的所有事情都可以使用 .NET 语言(如 C# 或 Visual Basic)完成。

例如,上述布局部分中的第一个示例:

<Border xmlns="/winfx/avalon/"><Canvas Background="silver" Margin="20" LayoutTransform="scale 2"><Button Canvas.Top="30" Canvas.Left="50">Hello world!</Button></Canvas></Border>

可以用 Visual Basic 重新编写为:

Dim myBorder As New Border, myCanvas As New Canvas, myButton As New ButtonWith myCanvas.Background = Brushes.Silver.Margin = New Thickness(20).LayoutTransform = New ScaleTransform(2.0, 2.0)End WithWith myButton.Content = "Hello World"End WithmyCanvas.Children.Add(myButton)Canvas.SetTop(myButton, 30.0)Canvas.SetLeft(myButton, 50.0)myBorder.Child = myCanvas or in C# as:Border b = new Border();Canvas c = new Canvas(); Button btn = new Button();c.Background = Brushes.Silver;c.Margin = new Thickness(20);c.LayoutTransform = new ScaleTransform(2.0, 2.0);btn.Content = "Hello World";c.Children.Add(btn);Canvas.SetTop(btn, 30.0D);Canvas.SetLeft(btn, 50.0D);b.Child = c;this.Content = b;

从这一简短示例中,您很可能会看到,XAML 提供了一个一致的、简洁的对象构建分层模型,并且不需要 Windows 窗体目前所需的隐藏代码区域。

但是,想必 XAML 不是其他 .NET Framework 语言的全盘替代物吧?显然,XML 标记不能替代复杂的构造和流控制逻辑,并且 XAML 的设计旨在将其与比较传统的编程语言一起使用。编译时,XAML 被编译为不完全类(这是 .NET Framework 2.0 中的一种新增功能,使您可将一个类定义扩散到多个文件中)内部的二进制表示形式。您可以使用选择的语言实现该类的另一半。例如,在 Visual Basic 中:

Partial Public Class Window1Inherits Window...End Classand in C#:public partial class Window1 : Window { ... }

您可以从自己的代码中自然地访问 XAML 中的任何命名元素(就好像已经在那里声明该元素一样),因为您的代码是同一个类的一部分。

XAML 的使用支持良好的体系结构原则,例如将模型和视图分开。开发人员和设计人员可以使用专门工具(例如,3D 设计工具、设计人员工具、开发工具、高端版式工具)协同工作;而且,只要这些工具全都发出 XAML,那么就可以将它们组合在一起来生成复杂的 UI。

返回页首

图形和文本服务

就像在引言中所强调的那样,当前的 Windows 图形平台 (GDI) 具有跨越将近二十年的传统。在过去几年中,3D 领域已经发生了巨大的变革,但 GDI 开发人员并未从中得到多少好处。目前的图形硬件进步主要集中于 3D 管线,并且 Windows Presentation Foundation 被设计为基于较旧的 2D 技术的完全战略替代物,并且最大限度地使用了现代 PC 的图形功能。图形的所有不同元素都经历了相同的管线:2D、3D、文本、图像和视频。

Windows Presentation Foundation 为应用程序和内容提供主流图形服务。它提供一个应用程序模型,而该模型利用在现代图形卡中流行的 3D 硬件支持。Windows Presentation Foundation 更加注重基于向量的内容;它提供分辨率独立性,将虚拟像素映射到逻辑像素,并且支持高 DPI 屏幕;本机坐标系基于双精度数据类型。新呈现模型的附带功能是,无需完成额外工作即可应用图像转换(例如,可将模糊效果或缩放因子应用于任何内容)。Windows Presentation Foundation 还是更为广泛的图形生态系统的一个必不可少的组件:例如,它利用新的 Windows Vista 显示驱动程序模型,它与打印模型共享功能,并且它具有通过终端服务实现的高保真远程处理。

3. The North Face店内资源管理器原型

图 3 显示在 PDC 会议上演示的高度浸入式应用程序体验。您在这里看到的所有内容均由 3D 驱动。文本利用了子像素 ClearType。进行了组合以创建视频控件:不同的内容类型放在一起以创建交互式体验。

Windows Presentation Foundation 开发有多个层。对于托管代码,大多数开发人员将在框架级别工作,并且使用 System.Windows.Shapes、System.Windows.Media 等命名空间中的对象,或者在较低的可视层级别工作以替换现有的图形后端(访问绘图基元,而无需利用布局和数据绑定等服务)。非托管代码也可以用来访问或扩展图像处理编码解码器等服务和效果。

2D图形

Shapes是开发人员可以使用的最基本的 2D 图形元素:它们包括画刷、画笔、几何图形、转换等。所有属性都是依赖性属性,这意味着可以将它们动画化、进行数据绑定等。

例如:

<StackPanel xmlns="/winfx/avalon/"><Slider Name="WidthSlider" Maximum="200" Minimum="10" /><Rectangle Fill="LinearGradient 0,0 1,1 #FF3366FF #FFFFFFFF" Height="100" Width="{Binding ElementName=WidthSlider, Path=Value}" /></StackPanel>

(在下文中,我们将更加详细地讨论数据绑定。)

在 Win32 中,即使是像这样的简单任务也需要多得多的代码,因为需要管理重新绘制。还请注意,像矩形 (Rectangle) 这样的形状派生于 FrameworkElement,这意味着它们参与布局系统。其影响是:在下面的代码中,随着矩形的大小增加,椭圆形会缩小以填充剩余的可用空间。

<DockPanel xmlns="/winfx/avalon/"><Slider Name="WidthSlider" DockPanel.Dock="Top" Maximum="200" Minimum="10" /><Rectangle Fill="Red" Width="{Binding ElementName=WidthSlider, Path=Value}" /><Ellipse Fill="Blue" /></DockPanel>

Brushes用于填充几何图形。可以采取多种不同的形式:纯色、渐变和平铺画刷可能是最常用的形式。如果您将大部分时间花在 XAML 中,则甚至无需实现纯色画刷就可以使用它。例如,上述示例中的矩形和椭圆形都使用了纯绿色的画刷:XAML 只是提供一种简略的“微语言”,能够将命名字符串转换为该颜色的画刷。

渐变画刷可用于细微的渐变或更为生动的效果。例如,请试验以下光学影像:

<Grid xmlns="/winfx/avalon/"><!-- Strange optical effect. Stare at this for a while and then change the first gradient stop from Black to LightBlue. For a while, itwill seem as if the gradient has disappeared altoghether. --><Rectangle><Rectangle.Fill><LinearGradientBrush StartPoint="0.0, 0.0" EndPoint="0.01, 0.03" SpreadMethod="Reflect"><LinearGradientBrush.GradientStops><GradientStop Color="Black" Offset="0.3" /><GradientStop Color="Silver" Offset="0.8" /></LinearGradientBrush.GradientStops></LinearGradientBrush></Rectangle.Fill></Rectangle></Grid>

ImageBrush 是一个平铺画刷,使您可以使用编码解码器所支持的任何图像(例如 PNG、JPEG 或 GIF)作为画刷。像任何平铺画刷一样,可以平铺或缩放 ImageBrush 的内容,并且可以使用转换来扭曲、旋转、缩放或平移图像。

最强大的画刷之一是 VisualBrush,它是一个 TileBrush,它包含的任何可视对象都是内容。通过 VisualBrush,可以对对象进行生动的“辅助”表示(例如,对于已打开的窗口,生动地显示其缩略图的工具提示),或者可通过将任何可视内容嵌入到画刷本身,并以某种方式对其进行转换,使用它来创建复杂的图形效果。

<StackPanel xmlns="/winfx/avalon/" LayoutTransform="scale 2"><StackPanel Name="reflectedPanel" Orientation="Horizontal"><TextBox Width="300" FontSize="48">Reflections...</TextBox><Button Content="OK" Margin="2" /></StackPanel><StackPanel Height="{Binding Path=(StackPanel.ActualHeight),ElementName=reflectedPanel}"><StackPanel.Background><VisualBrush Stretch="None" Opacity="0.75"AlignmentX="Left" AlignmentY="Top"Visual="{Binding ElementName=reflectedPanel}"><VisualBrush.RelativeTransform><TransformGroup><MatrixTransform Matrix="1,0,0,-1,0,0" /><TranslateTransform Y="1" /></TransformGroup></VisualBrush.RelativeTransform></VisualBrush></StackPanel.Background><StackPanel.OpacityMask><LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"><LinearGradientBrush.GradientStops><GradientStop Color="#FF000000" Offset="0.0" /><GradientStop Color="#00000000" Offset="0.8" /></LinearGradientBrush.GradientStops></LinearGradientBrush></StackPanel.OpacityMask></StackPanel></StackPanel>

SDK 提供了 VisualBrush 用法的进一步的示例。

如果您希望有一些可在整个应用程序中使用的图片,则可以使用drawing,它代表向量呈现指令。这些指令只需声明一次即可多次重新使用。能够说明这些指令如何有用的一个良好示例与向量图形或图标有关。绘图是在可视层操作的轻量级对象;例如,它们不参与布局系统,因此,当性能是最关键的因素时,它们十分理想。

Windows Presentation Foundation 中的一个更为有用的类使您可以用 DrawingBrush 类的形式将绘图和画刷组合在一起。这是一个可以应用于 2D 或 3D 表面的平铺画刷,它使您可以获取静态向量资源,并且在其他地方使用(例如,获取 UI 的背景中的向量填充)。

3D图形

在图形业中,有一种使用 3D 的发展趋向正在日益增长,然而目前对于大多数开发人员而言,这是一个具有挑战性的领域。当将 3D 设计到 Windows Presentation Foundation 中时,一个明确的目标是确保在 2D 和 3D 领域之间存在紧密的集成,以便降低这一转换的复杂性。3D 可以用在 2D 情景中,反之亦然;还可以将文本和媒体放在 3D 情景中。很多编程概念从 2D 转移到 3D 中,例如基于情景的编程和一致的类层次结构;此外,还有独特的 3D 功能,如照相机、模型、光源和材质。

主要对象之一是 Viewport3D,这是一个承载 3D 内容的 2D 元素。该元素描述了模型、光源和摄像机。Model3D 是与 2D 中的 Drawing 类似的 3D 对象;它描述了特定的 3D 几何图形。材质描述了纹理和光源特征。任何内容都可以是材质中的画刷,包括文本、视频、形状、绘图等。

手动创作模型是一件痛苦的事情;一个选择是使用诸如 Electric Rain 的 ZAM3D 这样的工具。还可以在用户界面中巧妙地使用 3D 以实现数据可视化(例如,3D 图表、2D 内容之间的转换和多个 2D 数据集的叠加)。

4.ZAM3D呈现的Channel 9 Guy

然而,不应该将Windows Presentation Foundation中的3D API视为DirectX的主要替代物。请将Direct3D用于浸入式3D游戏、大型3D应用程序(如CAD)和通用GPU方案。将Windows Presentation Foundation视为Direct3D “手动模式的自动等效物。

图像处理

Windows Presentation Foundation 通过编码解码器库为最常见的图像格式提供支持。要将图像嵌入到应用程序中,只需使用下面的 XAML:

<Image Width="200" Source="sampleImages/apple.jpg" />

请注意,图像从根本上说是矩形的,尽管可以用几何图形对其进行剪裁:

<Border xmlns="/winfx/avalon/" Margin="20"><Image Source="C:/WINDOWS/Web/Wallpaper/follow.jpg" Width="200" Height="150" HorizontalAlignment="Left"><Image.Clip><EllipseGeometryRadiusX="100"RadiusY="75"Center="100,75"/></Image.Clip></Image></Border>

您可以使用 ImageBrush 将图像作为纹理加以应用。例如:

<Ellipse Stroke="Purple" StrokeThickness="5.0"><Ellipse.Fill><ImageBrush ImageSource="table-bowl.jpg" TileMode="Tile" Viewport="0,0,.3,.3" /></Ellipse.Fill></Ellipse>

ImageSource 是向量或位图图像(分别为 DrawingImage 或 BitmapSource)的基类。

Windows Presentation Foundation 具有对元数据丰富且可扩展的支持,并且可以就地更新(这样,如果更改 JPEG 中的 EXIF 数据,它就无需读写整个文件)。还有简单明了的查询功能,因此您可以执行如下操作:

BitmapMetadata m = ((BitmapMetaData)myImage.Metadata); // get metadata from a JPEGstring focalLength = m.GetQuery("System.Photo.FocalLength"); string exposure = m.GetQuery("System.Photo.ExposureTime");

您甚至可以(从 TIFF 文件中)获取非键控的元数据:

string value123 = m.GetQuery("/ifd/{uint=123}"); // from a TIFF

媒体

在框架元素级别,有一个名为 MediaElement 的支持视频和音频的对象。可以使用时间线和时钟来控制该对象(播放、暂停、定位等)。Windows Presentation Foundation 支持 WMV、MPEG 和某些 AVI;在将来的版本中,媒体将能够与动画同步。

效果

位图图像效果获得 BitmapSource 并返回 BitmapSource。通常的用法将位图效果应用于可视树中的任何可视对象。在 PDC 版本中,只支持两种图像效果:模糊和投影;RTM 中将提供更多的效果。重要的是,图像效果模型可由其他人扩展 — 您可以创建自己的图像效果以供他人应用。

下面的示例说明如何使用它们:

<StackPanel.BitmapEffect><BlurBitmapEffect Radius="8" /></StackPanel.BitmapEffect>

动画

您可以将任何 Windows Presentation Foundation 对象上的依赖性属性动画化。动画可以发生在对象级别,但为了协调起见,更常见的做法是在故事板级别使用动画。动画基于时间,而不是基于帧 — 这提供了临时的分辨率独立性(每秒呈现多少帧没有关系:动画的速度独立于系统性能)。

故事板对触发器而非属性执行操作。触发器是事件驱动的(例如,Button.Click),并且它们可以驱动一个或多个操作,例如 ColorAnimation 或 DoubleAnimation,而这些操作又会面向多个元素的属性。下面的示例说明正在发生的动画:

<Pagexmlns="/winfx/avalon/"xmlns:x="/winfx/xaml/"><Ellipse Width="200" Height="200"><Ellipse.Triggers><EventTrigger RoutedEvent="Rectangle.Loaded"><BeginStoryboard><Storyboard><ColorAnimationFrom="Blue"To="Red"Duration="00:00:01"RepeatBehavior="Forever"AutoReverse="true"Storyboard.TargetName="gradientStop"Storyboard.TargetProperty="Color" /></Storyboard></BeginStoryboard></EventTrigger></Ellipse.Triggers><Ellipse.Fill><!-- Animated Linear Gradient --><LinearGradientBrush x:Name="brush" EndPoint="1,1"><LinearGradientBrush.GradientStops><GradientStopCollection><GradientStop Color="Blue" Offset="0" /><GradientStop x:Name="gradientStop" Offset="0.5" /><GradientStop Color="Red" Offset="1" /></GradientStopCollection></LinearGradientBrush.GradientStops></LinearGradientBrush></Ellipse.Fill></Ellipse></Page>

在这一简单示例中,圆看起来从左上到右下依次改变颜色,然后又依次恢复原来的颜色;同时,中间的 GradientStop 从蓝色到红色动画化,然后执行相反的操作。

动画是一个复杂的主题,它所提供的功能远远超出这一概述白皮书所能包含的范围。有关如何从代码中使用故事板的更多示例和详细信息,请参阅 SDK 文档。

返回页首

文本

Windows Presentation Foundation 使用 ClearType 引入下一代文本呈现功能,并且进行了很多新的发展,以进一步改善文本在计算机显示器上的可读性。

特别需要指出的是,三项新的增强功能已经被添加到 Windows Presentation Foundation 中的 ClearType:

在 Windows 3.1 中随附的很多“黑白”TrueType 字体(例如 Times New Roman 和 Arial)中,向很多标志符号中添加了提示,以便将自然推进宽度更改为能够获得更好的字符对称性的宽度。通常,宽度是按照 ±2 像素的幅度更改的。由于黑白像素的分辨率较低,所以对于阅读而言,对称性这样的因素要比字符宽度的准确性重要得多 (WYSIWYG)。因为可以沿“宽度”轴获得额外的分辨率,所以 ClearType 使我们可以同时获得标志符号的对称性和更准确的推进宽度。即使具有这一额外的准确性,仍然将 GDI 限制为以整数像素表示标志符号宽度,因此,最终所有宽度都舍入到最近的像素。

因为我们希望为 GDI 中系统上的所有字体启用 ClearType,所以我们需要使启用 ClearType 时的宽度与禁用 ClearType 时的宽度相同(这正是我们前面对字体修匀所做的事情)。为了获得这一行为,我们必须向 GDI 中添加一种叫做兼容宽度的模式,它会迫使推进宽度与黑白字体相同。为此,我们必须向标志符号中插入一个小误差。遗憾的是,该误差会使标志符号形状显著变形,并且在标志符号较小时,使不正确的灰度系数设置更成问题(这里,可以作为 Windows XP PowerToy 获得的 ClearType Tuner 会有所帮助)。

这意味着,对于 GDI,可以使用两个宽度选项:兼容宽度和非兼容宽度。通过添加某个误差,兼容宽度可以创建与黑白字体完全相同的宽度以及字体修匀。非兼容宽度被称为“自然宽度”,并且该模式在 Windows XP SP1 中变得可用。它提供了高质量的 ClearType,但是因为它位于 GDI 中,所以它仍然被限制为整数像素。

Windows Presentation Foundation 使用子像素定位的 ClearType,通过它可以在屏幕上显示完全精确的 ClearType。使用该选项,标志符号可以在任意像素位置开始和结束。这一功能(尤其是在与字距调整相结合时)使我们可以在显示器上显示高质量的字形状。高质量的间距是在屏幕上产生好看文本的重要组成部分。子像素定位使我们稍微损失了一点儿对比度,但出色的间距弥补了这一点。高精度间距使我们可以用设备无关方式定位文本。

最后,y 方向反别名修匀了纵轴上字符标志符号的边缘;尽管该功能无法利用该轴中的 RGB 子像素,但它仍然进一步提高了文本呈现的准确性。

Windows Presentation Foundation 中所有可以通过硬件加速的文本呈现功能都被赋予一个合适的卡,并且使用复合、筛选器和混合来承担原来需要在 CPU 上执行的工作。对于东亚字体的用户而言,Windows Presentation Foundation(其中,过去一直缺少 ClearType,并且字体尚未充分利用平台)中的增强文本支持尤其显著。

Windows Presentation Foundation 还支持很多新的 OpenType 字体功能,包括分数、随意和上下文连字、小号大写字母以及古代数字。下面这个简单的示例说明了上述新功能是如何造成巨大差异的。将下面的行输入到 XamlPad 并试验文本的呈现方式。(需要使用 Windows Vista 来完成该试验,因为只有在最新版本的操作系统上才能使用该字体。)

<RichTextBox xmlns="/winfx/avalon/" FontFamily="Segoe Script" FontSize="44" />

请注意,像“o”和“t”这样的单个标志符号是如何根据其上下文完全更改的。这基于字体中的附加提示信息,该信息告诉呈现引擎,根据其相邻字符选择哪个标志符号。特别地,对于脚本字体,这会产生更自然的“手写”外观。

对于更为生动的示例,请观察表示以下字体的优美方式(这要归功于 Windows Presentation Foundation 中对 Adobe Compact Font Format (CFF) 的支持)。以下为 Bickham Script Pro:

同样,请注意标志符号是如何根据上下文更改(r、y、l 和 g)甚至合并 (Th) 的。Windows Presentation Foundation 中自动提供了上述复杂功能。

在 Windows Presentation Foundation 中,您可以使用 TextBlock 或 TextFlow 类显示文本流。TextBlock 简单地显示单个文本块;TextFlow 在从 XAML 中使用以显示多个内容段落时是一个有用的类。在可视层,DrawingContext.DrawText() 是 GDI 领域的 DrawText 等效物,并且存在诸如 TextRun 和 Glyph 这样的类表示概念。最后,FormattedText 是一个在文本 API 中尤其有用的类。您可以获取一段文本,使用 BuildGeometry() 方法来提取向量几何图形,并且每当使用常规向量时使用它们。

除了对单个文本流的呈现支持以外,Windows Presentation Foundation 还包含一些强大的控件,以便改善阅读体验。例如,SinglePageViewer 类为流文档提供了一个容器,而该容器可以承载丰富的内容。对于 eBooks 以及其他需要显示大量文本内容的场合而言,该模型是理想的。

<SinglePageViewer xmlns="/winfx/avalon/" ><FlowDocument ColumnWidth="250" ColumnGap="20" ColumnRuleWidth="1" ColumnRuleBrush="Gray" IsColumnBalancingEnabled="False" Background="AliceBlue" FontFamily="Palatino Linotype" FontSize="14" Typography.DiscretionaryLigatures="True" Typography.NumeralStyle="OldStyle">

在 Windows 3.1 中随附的很多“黑白”TrueType 字体(例如 Times New Roman 和 Arial)中,向很多标志符号中添加了提示,以便将自然推进宽度更改为能够获得更好的字符对称性的宽度。通常,宽度是按照 ±2 像素的幅度更改的。由于黑白像素的分辨率较低,所以对于阅读而言,对称性这样的因素要比字符宽度的准确性重要得多 (WYSIWYG)。因为可以沿“宽度”轴获得额外的分辨率,所以 ClearType 使我们可以同时获得标志符号的对称性和更准确的推进宽度。即使具有了这一额外的准确性,GDI 仍然被限制为以整数像素表示标志符号宽度,因此,最终所有宽度都舍入到最近的像素。

因为我们希望为 GDI 中系统上的所有字体启用 ClearType,所以需要使启用 ClearType 时的宽度与禁用 ClearType 时的宽度相同(这正是前面对字体修匀所做的事情)。为了获得这一行为,我们必须向 GDI 中添加一种叫做兼容宽度的模式,它会迫使推进宽度与黑白字体相同。为此,我们必须向标志符号中插入一个小误差。遗憾的是,该误差会使标志符号形状显著变形,并且在标志符号较小时,使不正确的灰度系数设置更成问题(这里,Tuner 会有所帮助)。

<Paragraph><Floater Background="LightYellow" Padding="10" BorderThickness=".5" BorderBrush="Gray" Width="140"><Paragraph FontFamily="Calibri" FontWeight="Bold" FontSize="18">GDI Widths</Paragraph><List><ListItem><Paragraph>Compatible</Paragraph></ListItem><ListItem><Paragraph>Natural</Paragraph></ListItem></List></Floater>

这意味着,对于 GDI,可以使用两个宽度选项。首先是兼容宽度 — 通过添加某个误差,可以创建与黑白字体完全相同的宽度以及字体修匀。非兼容宽度称为“自然宽度”,并且该模式在 Windows XP SP1 中变得可用。它提供了高质量的 ClearType,但是因为它位于 GDI 中,所以它仍然被限制为整数像素。

Windows Presentation Foundation 使用子像素定位的 ClearType,通过它可以在屏幕上显示完全精确的 ClearType。使用该选项,标志符号可以在任意像素位置开始和结束。这一功能(尤其是在与字距调整相结合时)使我们可以在显示器上显示高质量的字形状。高质量的间距是在屏幕上产生好看文本的重要组成部分。子像素定位使我们稍微损失了一点儿对比度,但出色的间距弥补了这一点。高精度间距使我们可以用设备无关的方式定位文本。

</FlowDocument></SinglePageViewer>

您可以重新设置 SinglePageViewer 控件的样式,以匹配您希望提供的体验(例如,不同的按钮)。

批注

批注支持内置于两个基于 DocumentViewerBase 并且支持锚定流动和固定内容的文档控件中。这些控件分别是 SinglePageDocument 和 DocumentViewer。只需几行代码,开发人员就可以启用对添加和删除批注的支持。默认情况下,批注使用已发布的架构存储在 XML 流中。借助于附加的代码,开发人员可以实现自定义存储区,例如,将批注存储到隔离存储区,甚至使用 Web 服务将其存储到远程服务器中(例如,为了实现批注共享)。

Windows Presentation Foundation 中支持两种类型的批注:突出显示和注释。突出显示的工作方式就像用于书面读物的记号笔:可选择要用不同颜色设置的内容范围。另一方面,注释批注使您可以向一段内容中添加墨迹或文本内容,例如添加备注。像任何其他控件一样,可以设置注释批注的样式;例如,您可以为每个用户/注解者设置不同的背景注释颜色。

返回页首

样式设置和数据绑定

应用程序样式设置是一个概括性的术语,它涵盖了资源、样式、模板、触发器和故事板。样式集中定义了应用程序中元素的外观和交互行为。

Windows Presentation Foundation 在确定应用程序的外观方面为您提供了强大的功能,与 Windows 窗体(在基本自定义和所有者绘制模型之间存在巨大的落差)这样的技术相比,复杂性的提高程度更平缓一些。风险在于,应用程序作者试图使用每种技术(只是因为能够这样做),并且最终创建令人迷惑且令人讨厌的应用程序。创建设计良好的应用程序意味着其设计适合于应用程序和目标用户,具有艺术美感,改善了可用性,并且具有长久的生命力 — 第一百次使用该应用程序就像第一次使用时一样有趣。

样式

样式决定任何内容片段的外观。它们可以被命名(并且按名称使用),或者面向特定的控件类型 (Button),或者同时满足这两者。样式甚至可以基于其他样式。下面是一个创建按钮样式的简单示例:

<StackPanel xmlns="/winfx/avalon/" xmlns:x="/winfx/xaml/"Margin="15" LayoutTransform="scale 2" ><StackPanel.Resources><Style x:Key="MyStyle" TargetType="{x:Type TextBox}"><Setter Property="Background" Value="Green" /><Setter Property="Foreground" Value="White" /></Style></StackPanel.Resources><TextBox Style="{StaticResource MyStyle}">TextBox 1</TextBox><TextBox Style="{StaticResource MyStyle}">TextBox 2</TextBox><TextBox>Unstyled</TextBox></StackPanel>

在这段代码中,您会注意到,我们声明了一个资源词典,其中包含一个面向 TextBox 控件的命名样式。在该样式中,我们设置了两个属性 — 它的前景色和背景色。要利用该样式,只需将文本框设置为使用资源词典中的样式。请注意,第三个文本框没有引用命名样式,因此它接收默认样式。

模板

模板通过描述控件或数据类型的可视结构来扩展样式;Windows Presentation Foundation 的很多魔力正在于此。通过模板,您可以使用组合来描述对象的可视树。在以下示例中,我们用样式化的椭圆替换了默认按钮样式:

<StackPanel xmlns="/winfx/avalon/" xmlns:x="/winfx/xaml/"><StackPanel.Resources><Style x:Key="MyStyle" TargetType="{x:Type Button}"><Setter Property="Background" Value="SkyBlue" /><Setter Property="Foreground" Value="White" /><Setter Property="Cursor" Value="Hand" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Grid><Ellipse Name="rect" Fill="{TemplateBinding Property=Background}" /><ContentPresenter Margin="20,0,20,0"Name="content" TextElement.Foreground="{TemplateBinding Property=Foreground}" TextElement.FontSize="{TemplateBinding Property=FontSize}"VerticalAlignment="{TemplateBinding Property=VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding Property=HorizontalContentAlignment}" /></Grid><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="true"><Setter TargetName="rect" Property="Fill" Value="LightBlue" /><Setter TargetName="content" Property="TextElement.Foreground" Value="Black" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></StackPanel.Resources><Button Height="200" Width="400" FontSize="24pt" Style="{StaticResource MyStyle}">Click here</Button></StackPanel>

这里,您会看到,我们使用 ContentTemplate 内部的 ContentPresenter 来包含对象的实际内容(在这种情况下,是按钮的文本)。我们还将该椭圆内部的多个属性绑定到其父模板,以确保当开发人员设置按钮上的这些值时,能够对相应的基础元素进行更改。

触发器和故事板

可以将触发器与样式和模板配合使用,以便在用户和应用程序之间创建丰富的、动态的交互。当指定条件为真时,触发器被激发(在上述示例中,当鼠标移至按钮上方时,触发器被激发)。下面的代码片段是另一个示例 — 当元素获得焦点时,更改该元素的背景色:

<Trigger Property="IsFocused" Value="true"><Setter Property="Background" Value="Purple" />

您可以使用 setter 属性内的 TargetName="ContentBorder" 来面向对象的特定子元素(例如,ListBox 内的元素)。

事件触发器使您可以支持故事板,后者能够启用动画。如果不同时设置 To 和 From 属性,则即使该事件重写另一个设置事件,这一机制也可以毫无障碍地发生作用。

<EventTrigger RoutedEvent="Mouse.MouseEnter"><EventTrigger.Actions><BeginStoryboard><Storyboard TargetProperty="MaxWidth"><DoubleAnimation Duration="0:0:1" To="150" /></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger>

返回页首

数据绑定

每个应用程序都以某种形式使用数据。Windows Presentation Foundation 提供一组丰富的数据服务,使您能够绑定和操纵应用程序中的数据。

在大多数系统中,用户界面和数据是分开的,在逻辑结构和生成它的开发人员思想中都是如此。数据绑定是这两个实体之间的桥梁。但是,目前很多平台中的数据绑定都存在问题:它以黑盒的形式操作,不完全支持不同的数据模型(XML、关系、对象),并且它难以扩展。结果就是,很多人最后忽略了平台数据支持,并且编写他们自己的数据机制。

Windows Presentation Foundation 中的数据绑定模型试图解决这些问题。从 Windows Presentation Foundation 开始,数据已经成为一等公民;除 XAML 中的声明性支持以外,在属性引擎中还存在对数据的支持。Windows Presentation Foundation 支持三种类型的数据绑定:一次性(忽略服务器更新)、单向(只读)和双向(读写)。

基本数据绑定

需要完成的第一件事是创建数据提供程序。数据提供程序可用来连接到 XML、关系或对象数据源;还可以通过从抽象的 DataSourceProvider 类派生来创建自己的提供程序。

在该示例中,我们用内联 XML 数据创建一个提供程序:

<XmlDataProvider x:Key="nodePrototype" XPath="AuctionItem"><AuctionItem Description="AuctionItem" StartPrice="3.50"></XmlDataProvider>

接下来,我们只需绑定它。

<TextBox><TextBox.Text><Binding XPath="@Description" Source="{StaticResource nodePrototype}" /></TextBox.Text></TextBox>

如果在父容器内有多个绑定,那么可将 DataContext 设置为该源,这意味着无需不停地为各个绑定设置源。最后,标记扩展快捷方式使您可在对象本身内部编写 Value="{Binding XPath=@StartPrice}"。

使用列表内容

只绑定到单个项很难满足需要。更常见的情况是,您希望绑定到对象集合并且一起显示它们。Windows Presentation Foundation 提供了一个 ItemsControl 对象,您可使用它生成自己有关该信息的视图。例如,给定下面的数据源:

<AuctionItems><Item Title="Slightly unwashed, tatty teddy bear" /><Item Title="Threadbare pair of socks" /><Item Title="A used tea towel" /><Item Title="Packet of cereal, mostly uneaten" /><Item Title="A dead stick insect" /></AuctionItems>

您可以用下面的代码绑定它:

<StackPanel xmlns="/winfx/avalon/" xmlns:x="/winfx/xaml/"><StackPanel.Resources><XmlDataProvider x:Key="myItems" Source="c:/mydata.xml" XPath="/AuctionItems" /></StackPanel.Resources><Border><ItemsControl ItemsSource="{Binding Source={StaticResource myItems}, XPath=/AuctionItems/Item}"DisplayMemberPath="@Title" ></ItemsControl></Border></StackPanel>

ItemsControl 侦听对基础数据的更改并直接更新视图。它遍历各个项并且为各个项生成 ContentControl。ContentControl 使您可以按照您希望的方式呈现单块数据。在这种情况下,我们只显示默认内容:一个值被绑定到 @Title XPath 查询的标签。

数据呈现

在 Windows Presentation Foundation 中,我们为开发人员赋予了选择如何脱离绑定本身来呈现其数据的能力。数据模板提供一种以特定方式控制数据项的呈现方式。在数据模板中,可定义数据类型,这样该数据的所有实例都将以该方式显示。

在这种情况下,我们将使用 Windows Presentation Foundation 来创建使用 XAML 的 RSS 浏览器:

<DockPanel xmlns="/winfx/avalon/" xmlns:x="/winfx/xaml/" Margin="10"><DockPanel.Resources><XmlDataProvider x:Key="Blog" Source="/tims/rss.aspx" /><DataTemplate x:Key="TitleTemplate"><TextBlock Text="{Binding XPath=title}"/></DataTemplate></DockPanel.Resources><Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/title}" FontSize="24" FontWeight="Bold" DockPanel.Dock="Top" /><Label Content="{Binding Source={StaticResource Blog}, XPath=/rss/channel/description}" FontSize="18" DockPanel.Dock="Top" /><DockPanel DataContext="{Binding Source={StaticResource Blog}, XPath=/rss/channel/item}" ><ListBox DockPanel.Dock="Left" ItemsSource="{Binding}" ItemTemplate="{StaticResource TitleTemplate}" IsSynchronizedWithCurrentItem="True" /><Frame Source="{Binding XPath=link}" Width="Auto" /></DockPanel></DockPanel>

这里,数据模板用于定义如何显示列表框中的各个项。在这种情况下,我们简单地使用 TextBlock 来显示数据绑定项,但是我们可以轻松地对此进行扩展以显示图形、媒体、超链接或任何其他内容类型。Frame 控件被用作 IE 的宿主,以便显示任何单个张贴的详细信息。

显然,要生成功能完善的 RSS 浏览器,需要完成更多的工作:我们需要实现项缓存、读取/未读状态、多个快递、更好的样式设置以及更多的功能。但是,完全使用数据绑定仅仅实现这里显示的基本快递阅读器即可出色地证明 XAML 的威力。

组织数据呈现

开发人员希望能够对数据进行筛选、分组和排序。Windows Presentation Foundation 通过使用 CollectionView 对象对此进行支持。您可以同时具有同一个集合的多个视图。也可以通过任何数据形式使用它 — 只要它支持 IEnumerable。您还可以通过实现 ICollectionView 来实现您自己的排序、筛选和分组算法。

在资源部分中,添加下列代码片段之一:

<CollectionViewSource x:Key="SortByName" Source={StaticResource Blog}"<CollectionViewSource.Sort><scm:SortDescription PropertyName="@title" Direction="Ascending" /></CollectionViewSource.Sort></CollectionViewSource><CollectionViewSource x:Key="GroupByDate" Source={StaticResource Blog}"<CollectionViewSource.GroupBy><scm:PropertyGroupDescription PropertyName="@pubdate" StringComparison="OrdinalIgnoreCase" /></CollectionViewSource.GroupBy></CollectionViewSource>

要使用排序,只需绑定到新的键名称,而不是基础数据源。

对于分组,需要指定应该用于显示组标题的组样式,如下所示:

<ItemsControl ItemsContainerStyle="" ItemsSource="{Binding Source={StaticResource myItems}"><ItemsControl.GroupStyle><GroupStyle HeaderTemplate="{StaticResource groupingHeaderTemplate}" /></ItemsControl.GroupStyle></ItemsControl>

自定义数据呈现

最后,如果您根本不想将数据显示为列表,那么应该如何做呢?例如,如果您希望将信息显示为图表,那么应该如何做呢?这可以通过 Windows Presentation Foundation 实现。Windows Presentation Foundation 中的数据绑定支持扩展到了所有内容控件。例如,Button、Window、ToolTip 和 Label 都是 ContentControl。ListBox、ComboBox、TabControl 全都派生于 ItemsControl。

返回页首

文档服务

与 Windows Presentation Foundation 本身一起,Windows Vista 呈现技术包含两个用于处理文档和打印生存周期的新规范:

Open Packaging Conventions

Open Packaging Conventions 的使用有三种主要方案:

建议您对自己的文件格式使用 Open Packaging Conventions。如果这样做,则可利用常见的可用服务。

打包模型提供文件格式的基础 — 它在 Open Packaging Convention Specification(当前版本为 v0.75)中进行了说明。包可以由任何应用程序使用,并且目前有多个实现;除其他方面以外,Office 12 还将该规范用于其新的 .docx、.xlsx 和 .pptx 格式。可使用打包服务(部件和关系),或通过任何标准 ZIP 实用工具来访问该文件的内容。

文件 rels.relx 是文件的主索引:这里的链接指向包含元数据属性的其他 XML 文件、文档本身、缩略图等。

Open Packaging Convention API 驻留在 System.IO.Packaging 命名空间(位于 WindowsBase 程序集中)中。这里,您可以访问 Package、PackagePart 和 PackagePartCollection 等类。API 提供下列功能:打开和关闭包;创建和删除部件和关系;获得部件的名称、内容类型和流;读写部件流;获得关系的 ID、类型和 URI。如下所示:

const string relType = "/xps//06/fixedrepresentation";Package p = Package.Open("c://package.container", FileMode.Open); PackageRelationshipCollection packRels = p.GetRelationshipsByType(relType);foreach (PackageRelationship pr in packRels){Console.WriteLine(pr.RelationshipType);PackagePart part = p.GetPart(PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), pr.TargetUri));Console.WriteLine(part.ContentType + pressionOption);// do something with part.GetStream() here.}

对于打包内容的标头,有三个主要的可用服务。这些服务可用于对文档身份验证和内容的通用概念进行共享。它们如下所示:

数字签名提供一种验证签名内容未经篡改的方式,支持最终用户的拒绝需要。它可以用于所有 Open Packaging Convention 格式。证书与 XML 数字签名兼容,并且遵循 X.509 标准。选择对哪些部件进行签名是由签名策略决定的:例如,XPS 文档查看器策略会对所有已定义的部件和关系进行签名。证书可以存在于其自己的部件中,或者它们可以嵌入到签名部件本身中。可使用 PackageDigitalSignatureManager 类对文档进行签名:PackageDigitalSignature 类代表签名本身;还可使用它来验证签名。

权限管理。Open Packaging Conventions 规范并不要求使用特定的权限管理解决方案。但是,我们确实提供了一个可由任何面向 Windows Vista 的代码使用的默认解决方案,即 Windows Rights Management Services。该 API 存在于 System.Security.RightsManagement 命名空间中,并且可以用来将权限管理控件应用于实现该包的数据文件。

XML Paper Specification

XPS Document 格式可以视为自定义文件格式的一个示例。XPS 文档包含许多部件,包括:

在 XPS Document 中,存在特定的 API,可以取代包以获得文档解决方案。其中包括 XpsDocument、IDocumentSequenceReader 和 IFixedDocumentReader。这些 API 使您可以操纵文档:添加或删除部件、检索或设置核心属性 — 它们比基本部件 API 更为友好。

最后,可以通过使用标记兼容性来扩展 XPS Documents。这与 XAML 标记兼容性完全相同:您可以设置 Ignorable、ProcessContent、AlternateContent 和 MustUnderstand。

返回页首

应用程序模型

Windows Presentation Foundation 提供基元以帮助您管理应用程序内部的逻辑流。当我们观察现有的应用程序框架时,很多框架都有一些局限性。例如,只要应用程序适合 MFC 的结构,那么 MFC 就非常适于生成应用程序。如果超出界限,那么经常会发现 MFC 对您的妨碍。在某些情况下,缺少常见用户体验模型(例如,由 Web 浏览器推广的导航模型)的基础结构。最后,很多平台没有为应用程序级别的管理提供良好的隐喻(例如,在 Win32 中,您最终经常不得不将消息发送到其他窗口;在 Web 模型中,如果不使用 AJAX 等改良技术,则回发延迟是一个严重的问题)。

大多数应用程序需要下列服务:

该列表简要描述了 Windows Presentation Foundation 应用程序模型关注的领域。

常规应用程序服务

Windows Presentation Foundation 为数据管理、系统交互和 UI 模型提供了一系列自愿加入的服务;存在可用的基础结构,但它试图让您无法察觉。尽管如此,大多数应用程序还是需要一些通用的服务,并且 Windows Presentation Foundation 可以抽象这些服务(例如,资源管理)。最重要的是,生成基本应用程序的过程必须简单。(是否还有人记得在应用程序框架出现以前,生成标准的 Windows“hello world”应用程序需要几百行代码?)

任何应用程序的基类都是 元素。该元素对应用程序生存期 (OnStartup、OnExit) 和资源管理进行抽象,并且提供用于存储会话数据的属性包(有点儿类似于 所提供的属性包)。您还可以创建 Application 的子类以提供扩展的功能。最后,Application 类将 Win32 中的很多 WM_ 消息抽象为托管事件(例如,应用程序激活或停用)。

应用程序资源可以存储到四个不同的位置:嵌入到程序集中;本地存储为应用程序目录中的文件;存储到执行该应用程序的服务器上;或者存储到另一个程序集中。使用如下所示的代码来访问资源:

(请注意,在上述第三个代码片段中,siteoforigin 是一个固定关键字,而不是服务器名称的占位符。)

另一个有价值的服务是应用程序存储。传统上,应用程序经常将它们的数据存储到文件系统中,对于 Windows Presentation Foundation 而言,这仍然是一个选择。应用程序还有机会将其数据存储到单独的存储区域,这可以提供一个在不完全信任方案中受支持。为此,请使用 IsolatedDataFileStream 对象。其他选择包括 .config 文件或注册表(对于设置),甚至 Cookie(对于基于 Web 的应用程序)。

Windows Presentation Foundation 提供的第三个服务支持多个 UX 模型:既包括单文档界面 (SDI),也包括基于导航的界面。在基于对话框的 SDI 模型中,您使用窗口、对话框和控件;功能通常是通过菜单呈现给用户的。基于导航的应用程序使用 Page、Hyperlink 和 NavigationWindow 等 Windows Presentation Foundation 类来提供与 Web 隐喻更加匹配的模型。请注意,Windows Presentation Foundation 并不强迫应用程序只使用一个模型:我们经常看到很多应用程序基本上是基于窗口的,但使用基于页的模型来完成向导或其他“受控制的”任务。顺便说一下,Windows Presentation Framework 原本并不支持 MDI(多文档界面)模型;建议设计人员改而采用选项卡式模型(像 Visual Studio 那样),或多窗口模型(像 Microsoft Word 那样)。

对于导航窗口的主题,应用程序模型内的一个难题是:Web 上的超链接确实模拟了 BASIC "GOTO" 语句:它们不具有内置其中的起始页的概念。对于 Windows Presentation Foundation,该问题的解决方案是 PageFunction 对象,该对象更为紧密地模拟了 "GOSUB" 语句。从 XAML 中,使用 PageFunction 对象来取代 Page 对象;从调用代码中,随后可以创建该页函数的实例,为返回事件创建事件处理程序并且导航到它。在用户完成了与被调用页有关的工作以后,只需调用 OnReturn 事件,并且传递希望返回的任何参数。

基于Web的应用程序

Windows Presentation Foundation 并非仅适用于基于窗口的应用程序:我们还支持基于浏览器的应用程序。Web 浏览器应用程序 (WBA) 在安全沙箱中运行 — 它们无法调用特权服务,因而不需要任何安全或安装提示。它们不是以传统的意义安装,因此它们不会出现在“开始”菜单中,也不会在 /Program Files 目录中创建文件。它们是通过 ClickOnce(.NET Framework 2.0 的一部分)部署的。最后,它们是纯联机应用程序,因而不适合“有时连接的”方案。

对于同时提供浏览器宿主选项和独立选项的单个平台而言,它的一个优点是:二者的编程模型是相同的。与 Outlook 相比(Outlook 作为胖客户端和 Web (Outlook Web Access) 的两个完全不同的代码基而存在),该模型为那些需要支持 Web 或瘦客户端方法的应用程序提供了明显的优势。

如何创建 WBA?您可以使用 Visual Studio 中随附的模板,或者简单地在您的项目文件中设置三个属性:

<HostInBrowser>True</HostInBrowser><Install>False</Install><TargetZone>Internet</TargetZone>

如果要转换现有的应用程序,还必须删除不适合沙箱的代码 — 利用条件检查 (#if (WBA)...#else...#endif) 或通过使用权限级别的运行时检查。

返回页首

编写高性能应用程序

Windows Presentation Foundation 为编写丰富的应用程序提供了强大的功能,但是,它同时也可能带来性能问题,除非应用程序的设计考虑了目标计算机的不同特征。

Windows Presentation Foundation 适当地利用了硬件呈现。它使用 Direct3D 在 DirectX 7(或更高版本)上提供了加速呈现,并且用 DirectX 9 和 Pixel Shader 2.0 硬件进一步优化了图形卡。对于不具有上述功能的计算机,Windows Presentation Foundation 使用了软件呈现,即一个基于 CPU 的 SSE 和 SSE2 优化光栅化程序。当 Windows Presentation Foundation 无法使用硬件管线呈现某些内容,并且无法保证可以在所有计算机硬件配置中使用呈现输出时,也会使用该程序。

结果,Windows Presentation Foundation 同时具有硬件和软件管线,并且两者具有不同的性能特征。这可能使应用程序性能非常难以预测,因为存在两个代码路径。实际上,硬件确实要快一些;对于给定的应用程序,这只是一个设置最低要求的问题。Windows Presentation Foundation 支持简单的运行时硬件检测,并且允许您使用资源词典针对运行应用程序的平台动态调整该应用程序。

请使用如下所示的代码:

// tier will be 0, 1 or 2 where 2 is full hardware and 0 is softwareint wpfTier = System.Windows.Media.RenderCapability.Tier >> 16;// in this example, simply switch between software and hardware renderingif (wpfTier == 0)Resources.MergedDictionaries.Add(softwareRenderingDictionary);elseResources.MergedDictionaries.Add(hardwareRenderingDictionary);

Tier 的高序位包含层编号,并且还有一个可供您捕获的 TierChanged 事件(例如,退回到较低的电源管理模式)。0x20000 是高端硬件支持;0x10000 是基本的硬件呈现;0x00000 是软件呈现。在第 2 层开发计算机上,您可以通过使用“Display Properties”控制面板小程序上的“Troubleshooting”选项卡来切换到较低的层。

找到该层很容易,但创作适当的内容比较困难。请使用第 0 层计算机来创作静态的 2D 内容和简单的 2D 动画;第 1 层计算机还可以创作多个动画、不透明性和较大的填充区域;第 2 层最适合具有复杂 3D 内容和径向梯度的场景。

调试性能问题

请注意,软件呈现被用于某些操作,即使当应用程序在第 2 层硬件上运行的时候。例如,设置 TileMode=Tile 会导致通过软件光栅化程序呈现该元素。

Perforator 是一个新的 SDK 工具,它使您可连接到正在运行的 Windows Presentation Foundation 应用程序以检索性能度量。它还允许对 Windows Presentation Foundation 呈现进行实时更改,以帮助诊断性能问题。通过 Perforator,您可以连接到正在运行的 Windows Presentation Foundation 过程,并且可以将其设置为将所有已经退回到软件呈现的元素染为特定的颜色。

另一个工具是 ETW。诸如 tracelog、tracerpt 和 mofcomp 这样的工具可以记录和使用 ETW 事件。文档公开了我们支持的事件。

再次,您可以运行传统的分析来了解应用程序中的瓶颈。Enterprise Profiler Tool 随附于 Visual Studio 中并提供采样和规范模式。

最后,您可以使用 CLRProfiler(一个在 Microsoft Web 站点已经提供一段时间的现有工具)来跟踪托管堆分配问题,以及与其相关联的性能代价。

性能提示

可视化是一种改善数据密集型应用程序性能的很好方式。可通过 VirtualizingStackPanel 控件获得 Windows Presentation Foundation 中的 UI 可视化。对于大量的项而言,这要比 StackPanel 快 70 倍。您也可以做到同样的事情 — 如果能避免将所有对象一直保持在树中,那么您很可能会看到回报。

使用 XAML 中的资源和代码中的资源词典可以重用通用资源。对于多次重用的控件而言,这尤其重要。此外,请确保在任何“可冻结的”对象(如画刷或画笔)不再更改时将其冻结。这会减小它们的大小(因为 Windows Presentation Foundation 不必跟踪已更改的事件处理程序)并改善性能。

返回页首

互操作性和迁移

大多数看到 Windows Presentation Foundation 的开发人员都会关心对其现有应用程序产生的潜在影响。他们必须重新编写所有代码吗?是不是有更好的选择?插件和控件将会怎样呢?它们也都必须重新编写吗?

好消息是 Windows Presentation Foundation 提供了良好的互操作性:您可以在现有代码内部使用 Windows Presentation Foundation,也可以在 Windows Presentation Foundation 内部使用现有代码。但是,要获得最大的好处,百分之百的 Windows Presentation Foundation 体验确实能够提供混合方法所不具有的好处,例如,数据绑定、动画和所有元素的布局服务。

空域

让一段内容在另一段内容上呈现可能会出问题。例如,无法令人满意地生成 Alpha 混合透明度。空域的概念是“每种技术一个像素”。空域无需是矩形:我们支持 HREGIONS,但是我们不支持将分层窗口 (WS_EX_LAYERED) 用于所有有意义的用途。

下面的一些意见告诉您如何在应用程序中利用 Windows Presentation Foundation 以提供逐渐增长的好处,而根本无需重新编写它。首先,可使用它为您的 chrome(菜单、文本框、向导、帮助系统等)提供新的外观。其次,可将它用于您的应用程序画布,同时使 chrome 保持在 Win32 中。再次,如果您的应用程序提供生成 HTML 等输出格式的机会,您还可以支持 XAML 并集成到开发/设计工作区中。最后,您可以在 Windows Presentation Foundation 中包装现有的控件,以便将其公开给更广泛的受众。

迁移到/clr

将现有 Win32 C++ 应用程序迁移到 Windows Presentation Foundation 的首要步骤是将代码迁移到 Visual C++ ,以获得无缝托管代码集成的好处。迁移到 Visual C++ 的其他好处包括安全性 (/gs)、可靠性等。您很可能会获得编译错误,其原因在于增加的 ISO 标准符合性以及库及其头文件中的破坏性的更改。此外,您可能获得大量与安全问题或 64 位不友好代码有关的编译警告。第一步可能有点儿痛苦,但最终结果会让人觉得很值。

添加 /clr 也是行得通的,但是窍门在于知道在何处使用它。建议您只在相关的源文件上使用它。将它放在多个位置可能会降低编译速度,并且导致很多不必要的工作。例如,C 文件需要作为 C++ 进行编译,这将导致您遇到可能产生的所有源代码问题。另一个可能遇到的问题涉及到所包含头文件中的程序集代码。在 DllMain 中具有托管代码也会产生问题;有关该主题的详细信息,请参阅 Visual C++ 文档。

确保将调试器模式设置为mixed,就好像您只是用 /clr 开关编译一个 DLL;可能选择了错误的调试器(因为 Visual Studio 基于可执行文件的类型进行检查)。

Windows Presentation Foundation嵌入到Win32应用程序中

使其有效的秘诀在于将 Windows Presentation Foundation 应用程序逻辑放在 HWND 内部。您需要创建一个 HwndSource,它使 Windows Presentation Foundation 看起来像一个大的 HWND。

HwndSource source = new Source.RootVisual();

首先,需要通过添加 /clr 开关进行编译来添加 CLR 支持。其次,需要用 [System::STAThreadAttribute] 标记 WinMain。接下来,需要添加对下列组件的引用:PresenationCore.dll、PresentationFramework.dll、System.dll 和 UIAutomationTypes.dll。现在,我们为托管代码添加命名空间:

namespace ManagedCode{using namespace System;using namespace System::Windows;using namespace System::Windows::Interop;using namespace System::Windows::Media;}

现在,我们需要创建一个新的 HwndSource。使用如下所示的代码:

HwndSource^ source= gcnew HwndSource(...);UIElement^ page = gcnew AvClock::Clock();source->RootVisual = page;return (HWND) source->Handle.ToPointer();

难题

下面是您在采用这一路径之前可能希望考虑的一些难题:

if (Registry.LocalMachine.OpenSubKey("SOFTWARE//Microsoft//WAP" != null)// WinFX Runtime Components are installed

返回页首

小结

Windows Presentation Foundation 是对应用程序开发人员或设计人员工具箱的极大的增强。作为将来版本 Windows 的战略性呈现基础类库,它提供一个模型,该模型充分利用了基础图形硬件,并且为从独立应用程序到基于 Web 浏览器的应用程序再到文档的所有方面提供了支持。那些希望生成丰富的浸入式应用程序用户体验的应用程序开发人员,以及那些将要触及 Web 模型限制的人会因为及早采用 Windows Presentation Foundation 而获得特别的好处。

返回页首

可用资源

创作工具

Windows Presentation Foundation上的网络日记

转到原英文页面

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。