转载 如何让WPF与你的架构相适合收藏

WPF是一个新的客户端用户界面技术,是.NET 3.0 框架的一部分。软件设计者一直面临着为他们的应用程序选择一个正确的表示层技术。如果你一直在开发Windows平台下的应用程序,它的范围是狭窄的。要么你可以创建一个网络应用程序,一个智能的客户机程序,一个移动设备,或者是一些取决于目标对象的结合程序。你所选择的分别在.NET space - ASP.NET, Windows Forms和 Compact 框架里给你提供一个相当短的实用选项表。
   现在一种新的选择即将来临,你也要考虑这种新选择。WPF主要适合智能客户空间,但是网络空间里也有覆迭区。目前WPF没有应用于移动设备里,但是WPF Everywhere(即将面世的派生技术)在不久的将来会给设备带来某些新的性能。本文简单地讨论了WPF的关键概念。告诉你它是怎样适合你的表示层框架,以及怎样改变现在你开发客户应用程序的方式。本文也讨论了WPF与Windows Forms的互操作性,还将展现给大家一个例子:使用互操作性来逐步转移到WPF,而不必大规模的改动。

WPF概述


    当你接触WPF时,你第一个可能想到的问题就是我们为什么需要一个新的表示技术。我们给智能客户端提供了Windows Forms,为网络提供了ASP.NET。为什么不提高这些技术来增加新的性能呢?使用现有的技术来建立新功能的问题就在于经常把某些东西提高到一个新的水平,而你需要一个全新的基础来建立这些性能。你不能在只为两层楼而设计的板子上盖一座摩天大楼。你必须将它拆除,重新再建。当谈到设计表面层的解决办法时,网络在某些方面是很擅长,Windows Forms在其他方面很强。但是作为设计师和开发者,我们希望得到两者的优点。这就是WPF提供给我们的。
    WPF通过引进表示层技术打破了传统的Windows桌面应用程序,表示层技术主要集中在最佳化客户的感官体验,主要是视觉体验。网络已经进步相当大,使用图像、格式、文本,甚至音频及视频的结合体,在浏览器中比在Windows应用程序中更容易显示丰富的,视觉上更引人注目的内容。但是,由于网络分离的请求-应答模式,在网络上提供丰富的交互式体验比在Windows应用程序上更难。随着AJAX技术的引进,情况将会转好。但是,事实是如果你想最佳化用户的交互式体验,你需要一个可以利用桌面操作系统全部性能的应用程序。通过平衡客户机器性能,WPF在Windows应用程序里及通过网络更容易表现丰富的交互式图形。图1表示了由InterKnowlogy 开发的示例程序,此应用程序允许三维模式的交互式操作(选择与旋转)。
 
   

    图1 :InterKnowlogy 三维合作

   构建WPF应用程序其中一个核心概念就是用来构建应用程序的一切事物都只是一个元素。控件,形状,3维模式,图像,声音,视频,格式都只是元素。WPF可以让你很容易展现的元素包括:
• 贯穿应用程序元素的均一地使用的格式化内容(颜色,字体,图像,形状)
• 2维和3维形状,图像及模式
• 传统用户界面控件
• 任何元素的动画
   
    WPF的另一个关键特点就是:在开发windows应用程序时,增加了抽象性水平。首先在应用程序的用户界面控件、图形对象、格式及其他对象中有线模糊,所以能当做元素处理。你可以从单个元素或元素集中定义资源,通过应用程序使用这些元素。你可以对经过应用程序却没有在绑定控件间直接耦合的数据源或者是正在运行的数据进行定义。你甚至可以定义控件模板,从控件模板最初是怎样设计来渲染它本身出发,代替一个控件的表达渲染。
    WPF 也允许你使用新的XAML来用标记定义应用程序的静态结构。这个方法与ASP.NET使用标记从应用程序的动态行为中分离布局的方法相似。使用WPF,你可以表达XAML里所有的,部分的或者非XAML的逻辑。就像ASP.NET,XAML允许你在标记文件里包含脚本模块化一样,此标记文件中包括C#或者 VB代码,因此你能在XAML文件里编写整个应用程序。然而,在Visual Studio中使用XAML的默认方式就是使用XAML定义你的用户界面元素的结构,然后在单个C# 或者 Visual Basic代码后置的档案中使用程序设计代码来连接动态部分。然而,你可以不那样做,你可以用纯代码或纯XAML来编写整个应用程序,这在于此应用程序是用来干什么的,以及你想怎样管理这些代码。

 

   采用WPF
    WPF与.NET 3.0 Framework一起运转,支持Windows XP SP2, Windows Server 2003和Windows Vista。采用WPF时有一个关键因素。如果你不能在你的用户机器上安装.NET 3.0 Framework,你就不能使用WPF为客户应用程序服务。
    如果你马上使用WPF,另一个要考虑的关键因素与开发表示层技术的能力有关。尽管运转时间WPF 库是the .NET Framework 3.0的一部分,将在06年11月发行,但是WPF的设计时间工具在Visual Studio的下一个版本(叫做Orcas)发行时才会发行。现在有Orcas设计器的CTP版本可用于WPF,但是与Windows Forms 或是 ASP.NET 设计器比起来,CTP版本相当不成熟。现在也有Expressions Interactive Designer测试版(一种的新开发WPF应用程序的设计工具),但是在被承认是可用的产品代码之前,还有很长的路要走。它面向专业设计师而不是软件开发者,因此你将会体验到和在Visual Studio里不同的东西。
    由于WPF设计工具系列的现状,你必须仔细考虑是否在.NET 3.0发行时你就马上采用WPF还是等到设计工具更成熟时再用。如果你试图开发标准的商业应用程序(有很多传统控件例如按钮,文本框,组合框,数据网格),然后在使用WPF开发这些应用程序时,生产力可能不大。生产力的降低一部分是由于采用新技术要走一些弯路,但就算不会那么艰难,也会因为设计时间工具的不成熟导致你的发展计划受阻。你不得不使用XAML, C#或 VB代码,而不是使用设计器的拖放操作控件,来开发大部分的用户界面。在这一点上,WPF设计器中有一些控件拖放定义的性能,随着时间的推进,这些性能终究会成熟。但是现在对于定义你的windows版面布局及组合控件特性和数据绑定上,WPF设计器和 the Windows Forms 设计器之间在性能方面仍有很大的差距。现有可用的控件装置有一些缺点,由于明显缺乏数据绑定网格控件,使得在WPF中普通商业应用软件的使用情况比在Windows Forms中更困难。
    另一方面,如果你想采用WPF来利用WPF中丰富的图形处理能力,例如3d模式,动画,丰富的应用程序风格,使用WPF要比使用Windows Forms更快更清楚地完成这些任务。它真正取决于你想完成什么任务。代码按钮,文本框,窗体的交替使用可能会把你的应用程序的外观和图形性能发展到一个更高的水平。可视的引人注目的应用程序可以区别对待表面层技术的成功与失败,尤其当目标对象是消费者时。
    减轻主流商业应用程序生产力潜在损失的一个办法就是使用Windows Forms 和 WPF结合体。在本文后面讨论的两种技术有很好的互用性性能。当每一种技术都充分使用时,你可以在单个应用程序中利用互用性来使用Windows Forms 和WPF。你也可以使用这种性能逐步将现有的应用程序转移到WPF中。

WPF应用程序形式

   这里有两种WPF应用程序可供选择,传统windows桌面应用程序和XAML 浏览器应用程序。WPF windows应用程序以自己的过程在用户桌面上运转,可以利用客户机器上的.NET Framework, WPF,和其他资源的全部性能。XAML浏览器应用程序是在浏览器中运行的WPF应用程序。
   XAML浏览器应用程序是在浏览器中运行的WPF应用程序这一概念容易让人误解。WPF不是其他网络技术的替代品。网络浏览器客户技术最显著的特点就是它们能在多个浏览器和多个平台上运行。换句话说,你的用户可以运行在比在Windows桌面应用程序更广泛的配置上。一个XAML 浏览器应用程序和大型配套桌面WPF应用程序有相同的限制,即客户机器必须安装有.NET 3.0 Framework。那意味着客户机必须是Windows XP SP2或者更新版的。那是一个更有限制性的设置,而不仅仅说他们需要一个兼容的浏览器。
   要注意到XAML浏览器应用程序还有另外一个限制。他们只允许从代码访问安全区域运行的安全许可(基于你在浏览器内访问的地址)。这意味着每一个XAML浏览器应用程序将在局域网或互联网上运行,这有严格的限制许可。结果,使用XAML浏览器应用程序,除了显示丰富的图形或使网页呼叫回到原始站点,你不能做更多的事情。你的XAML 浏览器应用程序不能访问客户文件系统和数据库,除了回到它出发的原始网站外你不能使网页回到其他站点。 
   你可能会想既然有这么多缺陷,为什么还要使用XAML浏览器应用程序。我认为主要原因是如果用户通过现有的网站或入口实现你要的功能,就要展现一个一致的用户体验。通过使用WPF,你提供的体验比用其他网络技术提供的体验要更丰富,联系得更紧密。但是对于用户来说,他们好像进入到站点的另一页,而事实却是“那一页”正在使用WPF。如果在机器上安装了.NET 3.0这将是很显然的。 
 

WPF/e

   WPF/e是一种派生技术,它将扩大WPF的使用范围,允许你在WPF的基础上建立应用程序。这些应用程序既能在浏览器内运行,也可以被更广范围的客户(包括其他平台)运行。WPF/e不会在.NET 3.0内和WPF一起发行,但不久后将面世,很可能在2007年。 WPF/e在浏览器内使用一个ActiveX控件或其他形式的自动安装的宿主组件。此组件在没有依赖宿主浏览器的物体模块或特殊的脚本性能情况下,也能在浏览器内运行WPF内容和控件。一个简单的比喻就是把WPF/e看成和在浏览器内运行的和Macromedia Flash或Apple QuickTime相似的技术,其呈现的内容比浏览器本身呈现得更丰富。就WPF/e来说,将被提交的内容将是WPF应用程序。WPF/e支持的功能是WPF API全部性能的子集,而且也不是最终决定下来的。但是我期望这些性能与我前面谈到得XAML浏览器应用程序的性能相似——你可以处理丰富的图形,音频,还可以呼叫回到原始网址(可能在宿主网页内使用AJAX技术),但是与访问其他资源无关。然而,拥有一个好的从宿主站点显示服务的分布式结构能让你使用WPF/e实现许多功能。请关注更多即将发布的与WPF/e有关的信息。

开发WPF应用程序


   根据应用程序要做的任务来开发WPF的应用程序,可以选择纯代码方法,XAML代码方法或者两者的结合方法。后者将是最通用的,因为采用这样方法,你可以从这个设计工具中得到最大的利益,可维护性,灵活性,而且使你的代码更有表达力。基本上,你在WPF中所作的一切仅仅是针对WPF .NET类库中类型的代码,因而代码整个范围的功能性对你是可用的。使用XAML操作接口让你把可以更公开表达的对象设置在一种形式中,这种形式更方便于设计工具和设计者操作和定义。
一个WPF应用程序由一个层次的元素构成。最高等级的基本编程模式和Windows Forms并非很不相同。你创建一个应用程序类别的实例,从Windows类别(或一个派生类别)创建一个最高等级的窗口,并运行这个程序。和VB Windows Forms应用程序一样,如果你没有明确地创建一个你自己的进入点,这个进入点(主方法)将自动产生。
例如,在下面图2中的两个XAML文件公开创建了一个应用程序类实例和一个窗口类实例。这个窗口有它的第一个子要素作为网格。在WPF中,这个网格控件就像一个HTML表格或使Windows Forms2.0中的表格设计面板。它仅能提供给你一个矩形网格容器,你能够把其他元素放置在里面用于设计。在网格之内,XAML定义了两行两列,然后使用附加属性放置两个文字块控件和两个文本框控件在这个网格单元中。

// App.xaml
<Application x:Class="SimpleWPFApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"/>

// Window1.xaml
<Window x:Class="SimpleWPFApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title=" SimpleWPFApp" Height="100" Width="270">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0">Name:</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0">Phone:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Width="150"/>
<TextBox Grid.Row="1" Grid.Column="1" Width="150"/>
</Grid>
</Window>
   产生的应用程序如图2所示。这个窗口显示了Windows Vista边框和标题栏风格,那是我一直用的。
   如果在Windows XP和Server 2003上运行,将会有这些操作系统的标准标题栏和边框风格。
 
    图3运行XAML应用程序

   同样的应用程序能用纯代码的方式来表示。
class Program
{
[STAThread]
static void Main()
{
Application app = new Application();

Window win = new Window();
win.Width = 270;
win.Height = 100;
win.Title = "SimpleWPFAppCodeOnly";

Grid grid = new Grid();
win.Content = grid;

RowDefinition row1 = new RowDefinition();
row1.Height = new GridLength(0, GridUnitType.Auto);
RowDefinition row2 = new RowDefinition();
row2.Height = new GridLength(0, GridUnitType.Auto);
grid.RowDefinitions.Add(row1);
grid.RowDefinitions.Add(row2);

ColumnDefinition col1 = new ColumnDefinition();
col1.Width = new GridLength(0, GridUnitType.Auto);
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(0, GridUnitType.Auto);
grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);

TextBlock label1 = new TextBlock();
label1.Text = "Name:";
grid.Children.Add(label1);
TextBlock label2 = new TextBlock();
label2.Text = "Phone";
grid.Children.Add(label2);
TextBox tb1 = new TextBox();
tb1.Width = 150;
grid.Children.Add(tb1);
TextBox tb2 = new TextBox();
tb2.Width = 150;
grid.Children.Add(tb2);

Grid.SetColumn(label1, 0);
Grid.SetColumn(label2, 0);
Grid.SetRow(label1, 0);
Grid.SetRow(label2, 1);
Grid.SetColumn(tb1, 1);
Grid.SetColumn(tb2, 1);
Grid.SetRow(tb1, 0);
Grid.SetRow(tb2, 1);

app.Run(win);
}
}


    正如你在纯代码版本中所看到的,尽管XML比代码更冗长,在许多WPF元素的情况下,XAML实际上更加紧凑。因为通过XML内联属性很多属性能够单独的被设置而不需要单独的一行代码来设置。同样的,你不必加入一个元素作为另一个元素的子元素,因为在可扩展应用程序标记语言XAML标签的嵌套里,那种关系是隐式的。
   你也可以从代码看到由XAML产生的成分并非完全不同于你在Windows Forms或者ASP.NET中所做的。这个窗口是最高层元素,增加网格作为子元素,加文本块和文本框控件作为网格的子元素等等。
   当你开始连接事件处理器控制事件时,你经常会通过C#或VB代码来实现。XAML代码编译成一个部分类,你可以通过另一个部分类文件加任何代码到这个部分类中。在这一点上,Visual Studio遵循一种同样的ASP.NET方法,它为操作接口创建一个Window1.XAML文件,并在部分类中为代码隐藏创建一个Window1.XAML.cs文件。
   另一件你可能尝试理解的事情是XAML属性或者代码行,在那里,你明确指明包含的控件在哪一行、哪一列。这样做用到了WPF中的一个新的概念,附加属性。在XAML中,看上去有称为Grid.Row和Grid.Column的属性,Grid.Row和Grid.Column定义在控件类上。为每一个他们能用到的可能的文本中的控件明确地定义属性,会导致对象模型混乱。但是,单独的代码版本让我们更清楚实际上什么正在运行。附加属性要求网格上的动态方法建立一个与被包含的控件相联系的网格级的属性。如果你接触过Windows Forms扩展提供控件,其概念和这里的是相似的。
    建立更复杂的WPF应用程序遵循你在这里所看到的相类似的模式。定义层次结构上的更多元素,此层次结构包括你的应用程序的窗口。这些元素可能是容器控件的任何组合,例如网格,个别控件比如文本框,式样,几何,动画时间标尺和情节串连图板,3维模型,视频等等。