Windows Presentation Foundation
本书介绍了应用程序的两种主要类型:用户直接运行的桌面应用程序和用户通过浏览器访问的Web应用程序。我们在.NET Framework的两个不同区域创建它们:Windows窗体和ASP.NET页面。这些应用程序类型有各自的优缺点。桌面应用程序有较大的灵活性和较强的响应性,而Web应用程序可以被许多用户同时在远程访问。
在目前的计算环境下,应用程序之间的界限越来越模糊了。有了Web服务和Windows Communication Foundation(WCF,详见第35章)后,桌面应用程序和Web应用程序都可以用更分布的方式执行,在局域网和广域网上交换数据。另外,Web客户应用程序(即IE或Firefox等浏览器)不再被看作所谓的“瘦”客户程序,因为它们不再仅仅显示信息。最新的浏览器和运行它们的计算机的功能已经远不止此。
近年来,用户体验的个性化已经渐成气候。Web应用程序现在一般使用JavaScript、Flash、Java应用程序和其他技术,越来越像桌面应用程序了。例如,Google Docs的功能就说明了这一点。而桌面应用程序相互连接的趋势越来越明显,其功能从简单(自动更新、在线帮助等)到高级(例如,在线数据源和对等联网),应有尽有。这一点可以通过图34-1来说明。
图 34-1
Windows Presentation Foundation(WPF)是一种统一的技术,利用它编写的应用程序可以在桌面和Internet之间搭起桥梁。本章介绍的WPF应用程序可以作为桌面应用程序运行,或在浏览器上作为Web应用程序运行。WPF有一个删节版本Silverlight,可用于给Web应用程序添加动态内容。
本章将学习WPF,理解如何使用它创建下一代应用程序,主要内容如下:
● WPF的概念
● 基本WPF应用程序的组成
● WPF基础
● 用WPF编程
34.1 WPF的概念
利用WPF(以前称为Avalon)技术可以编写出独立于平台的应用程序,它清楚地定义了设计和功能之间的界限。WPF借用并扩展了以前许多技术的概念和类,包括Windows窗体、ASP.NET、XML、数据绑定技术、GDI+等。如果读者以前使用.NET Framework创建过Web应用程序,第一次看到WPF应用程序的代码时,会立即注意到许多类似之处。尤其是,WPF应用程序使用标记和后台编码模型,这与ASP.NET类似。但在其内部,它们的不同点和相似点一样多,因此WPF对于开发人员和用户而言都是一种全新的技术。
WPF开发的一个关键概念是设计与功能几乎完全分开。这样,设计人员和C#开发人员就可以一起开发项目,其自由程度可以达到以前高级设计概念或第三方工具的要求。这个功能受到所有人的欢迎,包括小型团队、爱好开发的人员、合作开发大项目的大型开发团队和设计人员。
下面几节介绍WPF给设计人员和开发人员带来了什么好处,使他们能携手工作。
34.1.1 WPF给设计人员带来的好处
在WPF中,用户界面设计使用的语言是Extensible Application Markup Language(XAML,读作zammel)。它类似于ASP.NET中使用的标记语言,因为它也使用XML语法,允许以声明性的、带层次结构的方式把控件添加到用户界面上。也就是说,可以用XML元素的形式添加控件,用XML属性指定控件的属性。控件也可以包含其他控件,这对布局和功能都非常重要。
但是,XAML比ASP.NET强大许多,在显示给用户时绝不仅限于HTML的功能。XAML在设计时考虑了目前强大的图形卡,并允许使用这些图形卡通过DirectX 7或更高版本提供的全部高级功能。下面列出了这些功能:
● 浮点数坐标和矢量图提供的布局可以缩放、旋转和转换,且没有质量损失。
● 高级显示的2D和3D功能
● 字体的高级处理和显示
● UI对象的纯色、渐变色和纹理填充,且可以设置透明度
● 动画故事板功能,可以用于所有情形,包括用户触发的事件,如鼠标单击按钮事件
● 可重用的资源,以动态设置控件的样式
许多功能都专门面向Microsoft Vista操作系统,该操作系统可以通过Aero接口访问高级图形功能。但是,WPF应用程序也可以运行在其他操作系统上,例如Windows XP。如果图形卡因某种原因无法工作,内置于.NET Framework 3.5运行库中的支持显示系统可以显示XAML(但有性能损失)。
VS和VCE包含创建XAML代码并设置其样式的功能,但设计人员选择的工具是Microsoft Expression Blend(EB)。这是一个设计和布局软件包,可用于创建XAML文件,接着开发人员就可以使用XAML文件创建应用程序。实际上,EB使用与VS和VCE相同的解决方案和项目文件,所以可以在这些环境中的一个中创建项目,在另一个环境中编辑它。在EB中,在编辑后台编码文件时,只需在Files窗口(等价于VS和VCE中的Solution Explorer)中双击它。图34-2显示了EB界面。
图 34-2
在microsoft.com/expression/products/overview.aspx?key=blend上可以找到有关EB试用版本(和EB2,在编写本书时,它正在开发)的许多信息,并可以下载。但是,编写WPF应用程序或编辑XAML并不需要EB。图34-3显示了图34-2中的项目,但该项目在VCE中加载。
图 34-3
提示:
在VS和VCE的2005和2008版本之间有一个区别,它会妨碍EB当前版本的使用。但是,可以使用一个配置工具,重新配置EB,以使用VS2008和VCE 2008。这个应用程序可以从http://blogs.msdn.com/expression/archive/2007/05/29/working-with-visual-studio-code-name-orcas-and-expression-blend.aspx上获得。
在运行配置程序(BlendConfiguration.exe)时,选择把EB配置为使用Visual Studio代码名Orcas。
这个问题有望在EB或EB2的未来版本中解决。
在VCE中,默认屏幕会在两个窗格上显示XAML(目前不必考虑显示在XAML视图中的代码)和这些XAML的预览。属性编辑器不太直观,选择对象时,这个编辑器有一些略微古怪的特性。在图34-3中,选择了Label控件,但选区不完全匹配这个控件。
应用程序在两个环境中加载的效果相同,如图34-4所示。
图 34-4
34.1.2 WPF给C#开发人员带来的好处
如上一节所述,开发人员可以创建能在VS或VCE中工作的项目和解决方案,而设计人员可以在Expression Blend中编辑这些项目和解决方案。但与设计人员不同,开发人员主要在VS或VCE中工作。
如本节的引言所述,WPF使用与ASP.NET非常类似的后台编码模型。例如,把Click属性添加到表示按钮控件的XML元素中,就可以给按钮控件添加一个事件处理程序。这个属性在XAML页面的后台编码文件中指定了事件处理程序的名称,事件处理程序可以用C#编写。
注意,还可以在WPF应用程序中操作控件,其方式类似于Windows窗体应用程序使用编程技术布置用户界面。可以使用后台代码实例化控件,设置其属性,添加事件处理程序,给窗口添加控件,这完全绕过了XAML。其代码一般比对应的XAML声明代码长得多,且无法分隔开设计和功能。编程方式在某些情形下是必须的,但一般应使用XAML来布置用户界面上的控件。
本章主要从C#开发人员的角度来阐述。WPF是一个需要一本书来介绍的主题,所以本章仅简要探讨它。
34.2 基本WPF应用程序的组成
WPF使用起来很直观,学习它的最佳方式是开始使用它。如果读者已经阅读了本书的其他章节,就会很熟悉许多技术。
下面的示例要创建一个简单的WPF应用程序,在该示例的说明中,会详细探讨代码和结果,了解如何把代码组合起来。
试试看:创建一个基本的WPF应用程序
(1) 创建一个新WPF应用程序Ch34Ex01,将其保存在C:\BegVCSharp\Chapter34目录下。
(2) 修改Window1.xaml中的代码,如下所示:
(3) 双击设计视图中的Toggle按钮,如图34-5所示,它会隐藏XAML视图。
图 34-5
(4) 修改Window1.xaml.cs中的代码,如下所示(双击按钮时,会在toggleButton_Click()事件处理程序中添加using语句和新代码):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
namespace Ch34Ex01
{
/// < summary >
/// Interaction logic for Window1.xaml
/// < /summary >
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void toggleButton_Click(object sender, RoutedEventArgs e)
{
Storyboard spinStoryboard = Resources[“Spin”] as Storyboard;
if (spinStoryboard != null)
{
if (spinStoryboard.GetIsPaused(this))
{
spinStoryboard.Resume(this);
}
else
{
spinStoryboard.Pause(this);
}
}
}
}
}
(5) 执行应用程序,开始、停止、切换动画,示例如图34-6所示。
(6) 创建一个新的WPF浏览器应用程序Ch34Ex01Web,将其保存在C:\BegVCSharp\ Chapter34目录下。
(7) 在page1.xaml中把元素的Title属性的值改为Color Spinner Web。
(8) 打开Ch34Ex01应用程序中的Window1.xaml文件,把该文件中元素的所有代码复制到page1.xaml的元素中。
图 34-6
(9) 把、和元素改为、和元素(注意,要修改这些元素的开闭标记)。
(10) 从page1.xaml中删除5个元素及其内容。
(11) 把toggleButton_Click()事件处理程序和System.Windows.Media.Animation名称空间的using语句从Window1.xaml.cs复制到page1.xaml.cs中。
(12) 执行Ch34Ex01Web应用程序,结果如图34-7所示。
图 34-7
示例的说明
这个示例创建了一个简单的应用程序,得到可以开始或停止的颜色旋转椭圆。但黑白屏幕图不能完全表达这种效果,只有运行代码,才会发现应用程序很漂亮。
为了达到这种效果,添加了许多代码,但如果仔细查看代码,就会发现许多代码都是重复的——这是必要的,因为要连续改变4个椭圆。另外,在后台编码文件中几乎没有添加什么C#代码,仅为一个按钮添加了代码。以这种方式设计代码说明了两点:
● 设计人员可以仅用XAML代码创建出漂亮的用户界面,其中涉及高级图形功能、动画和用户交互操作。
● 需要时可以在后台编码文件中完全控制XAML用户界面。
我们还介绍了如何在Web应用程序中使用与桌面应用程序相同的代码。这需要进行几处修改,如后面所述,但基本功能在两个环境中是相同的。
这个应用程序中的代码演示了WPF的许多特性,介绍了一些关键技术。首先创建桌面应用程序,再看看Web应用程序需要的修改。下面列出了桌面应用程序Window1.xaml的XAML,以及这些代码的顶级元素:
< Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Ch34Ex01.Window1"
Title="Color Spinner" Height="370" Width="270">
...
< /Window >
元素用于定义窗口。一个应用程序可以包含几个窗口,每个窗口都包含在一个单独的XAML文件中。但这并不是说XAML文件总是定义一个窗口。XAML文件可以包含用户控件、笔刷和其他资源、Web页面等。Ch34Ex01项目中的XAML文件甚至定义了应用程序App.xaml。本章后面会介绍应用程序和App.xaml文件。
在Window1.xaml中,注意元素包含一些非常简单的属性。其中有两个名称空间声明,每个都用于全局名称空间,其中一个名称空间用于XML,另一个用于x名称空间。这两个名称空间对于WPF功能来说非常重要,定义了XAML语法的语义。接着是一个Class属性,它取自x名称空间。这个属性把XAML 元素链接到后台编码文件中的一个部分类定义上,在这个例子中是Ch34Ex01.Window。这类似于ASP.NET,一个类用于一个页面,并允许后台代码与XAML文件共享相同的编码模型,包括XAML元素定义的控件。注意,x:Class属性只能用于XAML文件的根元素。
其他3个属性Title、Heighth和Width指定了在窗口标题栏中显示的文本以及用于该窗口的尺寸(单位是像素)。这些属性映射到System.Windows.Window类的属性上,Ch34Ex01. Window派生于System.Windows.Window类。
System.Windows.Window类有其他几个属性可以定义额外的功能。许多属性都比元素上使用的属性复杂,它们不只是字符串或数字。XAML语法允许使用嵌套的元素,为这些属性指定值。
提示:
在“XAML语法”一节详细讨论了定义对象、属性和内容的XAML语法。
例如,下面的代码用一个嵌套的元素定义了Background属性:
< Window.Background >
< LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
< GradientStop Color="#FFFFFFFF" Offset="0"/ >
< GradientStop Color="#FFFFC45A” Offset="1"/ >
< /LinearGradientBrush >
< /Window.Background >
这段代码把Background属性设置为LinearGradientBruch类的一个实例。WPF使用笔刷的方式类似于第33章讨论的GDI+。在这个示例中,笔刷定义了一个自上而下从白色过渡到桃色的渐变色。
这段代码在嵌套的元素中还定义了另外两个复杂的属性:定义动画的和定义触发器的,它控制动画。这两个属性的功能都远不止此,本章后面会详细介绍它们。
在查看这些属性的执行代码之前,需要先看看元素。元素定义了System.Windows.
Controls.Grid控件的一个实例。 这是可以在WPF应用程序中用于布局的几个控件之一。它允许用相对于矩形4条边的坐标来定位嵌套的控件。其他控件可以用不同的方式定位控件。所有的布局控件都在本章后面的“控件布局”一节中介绍。
元素包含5个元素(System.Windows.Shapes.Ellipse控件)和3个
(8) 运行应用程序,把鼠标停放在按钮上,如图34-17所示,按钮会闪动并发光。
(9) 单击按钮,如图34-18所示,发光效果改变了。
图 34-17
图 34-18
示例的说明
这个示例完成了两个工作。第一,定义了一个全局资源,用于格式化应用程序中的所有按钮(目前只有一个按钮,但这不重要)。第二,给上一个示例创建的样式添加了一些特性,使该样式能被接受。该样式会闪动并发光,以响应鼠标停放在按钮上和单击按钮操作。
把样式设置为全局资源,只需把