作者:Dino Esposito
翻译:winsome zhong
从各方面来讲,微软的下一代视窗即代号为“Longhorn”的操作系统,都是Windows产品中一个非常重要的里程碑。“Longhorn”是首个用托管代码构建的操作系统,采用了微软最新的存储子系统“WinFS”,支持一种更为高级的自然搜索技术(Natural UI)以及最新的安全架构“Palladium”, 在Windows的历史上,我记得也就只有两个这样重要的里程碑,一个是Windows由16位向32位的迁移,另一个是.Net的诞生。当然,“Longhorn”这些令人兴奋的新特性同时也表明我们以往驾轻就熟的开发方式将发生重大的变化(呵呵,最近对于微软开发技术和开发工具更新太快的怨言好像越来越多了,但抱怨归抱怨,我相信“Longhorn”全新的开发模型肯定会让你精神振奋的)。其中最为重要的一个改变是 “Longhorn”使得应用程序可以一次编码,多场景部署。为实现该功能,基于“Longhorn”的应用是完全面向对象的,整个应用派生于一个核心对象Application,该对象提供了运行整个应用程序所需的所有核心功能。本文将带领大家体验最新的Longhorn应用模型,并演示一些基本的例子,其中当然包括经典的“Hello World!”。
一、Longhorn应用模型
Application对象是Longhorn应用模型的核心,通过它的属性、方法和事件,你可以像编写网页一样使用一种增强的html来编写传统的Windows窗体应用程序。Application是一个Longhorn应用程序的根对象。它提供了应用程序的基本功能,可用于一些低级的、不需要在窗体间导航和维护状态的程序 ,但更复杂的Longhorn应用程序要使用NavigationApplication对象,这是一个Application的子类 ,增加了对导航的支持。
一个典型的Longhorn应用程序可以被看作一系列带有程序脚本的页面(叫做Page),并由Application对象控制程序的执行。Page使用一种新的标记语言来编写,这种标记语言的代号是“XAML ”(Extensible Application Markup Language)。通过XAML的元素标签你可以控制Page的布局,包括显示文本和图片,插入按钮、文本筐等交互式控件。一言概之,“XAML”是用来编写Longhorn应用程序UI界面Page的标记语言。当然,除了使用XAML,你也可以完全使用程序代码来编写应用程序。一般来说Longhorn程序会同时使用XAML和托管代码。你可以按自己的方式来组合它们。
使用XAML和C#(或VB.NET),你可以构建各种类型的应用输出文件,传统的exe执行文件,DLL 库,或者Console应用程序。而且,如果你的应用程序足够简单的话,你也可以完全使用独立的XAML标签来编写它,这样在longhorn中就多了一种类型的程序。当独立的XAML文件没有引用别的后台类时,它可以直接在Longhorn Shell和浏览器中运行。其实Longhorn的可执行文件都是既可以运行在Windows中,也可以运行在浏览器中的,你无需对程序的代码做任何的修改,只要在编译的时候设置不同的项目属性就行了。
对于Longhorn,可执行程序是今天Windows窗体程序的下一个版本。但从另一方面来说,XAML以及基于浏览器的应用程序也代表了应用程序做为web客户端的开发模式的一次革新。目前,Windows窗体客户端程序很少被发布到web上,因为如果你想把Windows窗体嵌入到浏览器网页中,你会受到诸多限制,还必须对代码做相应的修改。而在Longhorn中,通用的应用模型使你可以编写一个程序并通过web来部署。不过,这与我们传统的web应用(比如Asp.Net)有很大的区别,这是Longhorn专有的应用程序。
当你编译一个应用时,代号为“Whidbey”的下一个版本的Visual Studio和.Net Framework(或者说它底层的MSBuild.exe工具),会生成一个.exe文件,一个程序文件清单(扩展名是.manifest)和一个部署文件清单(扩展名是.deploy).当你点击.exe文件,程序会如你所期望的那样运行于Windows中。但是如果把程序设置为在浏览器中运行,那点击.exe文件时IE会自动跳出来并在其中运行程序。还有一种可选的方式是把程序部署在远端服务器上,步骤如下,首先把.deploy文件拷贝到服务器的合适位置,可以是FTP或HTTP的相对路径下。然后把编译后的程序文件和.manifest拷到服务器上,程序文件、.manifest文件不一定要和.deploy文件放在一起。如果放在不同的地方,你可以编辑.deploy文件,使它指向.manifest文件。.manifest文件和.deploy文件都是xml文件。当用户通过浏览器访问部署文件,Longhorn会自动下载程序文件及.manifest文件并安装到用户电脑上,同时还创建一个指向.deploy文件的快捷方式。用户点击.deploy文件就可以执行程序。
所有Longhorn的应用程序的通用结构都是这样的:XAML Page加上程序代码(内嵌或者使用Code Behind技术),根对象派生于Application。Application对象是程序的控制器,它的生命周期和程序的生命周期是一样的。通过Application对象,你可以处理高级事件、在Page间共享代码和状态等等。它同时也负责根据程序的逻辑让用户在Page间导航,用户在使用软件完成功能时会在Page间来回跳转,跳转时Longhorn一般会使用新的Page代替旧的,当然,你也可以选择弹出一个新的窗口来显示新Page。导航并不是每个程序必需的,简单的只有一个Page的程序就不需要了。
刚刚提到XAMLPage可以嵌入程序代码作为标签的补充。程序代码是必需的,比如处理一个由XAML元素产生的事件。程序代码既可以嵌到XAML文件中,也可以放在代码文件中。
Longhorn的编程是基于托管代码的,不过目前只有几种兼容.Net的语言可以用于编写基于XAML的程序,包括C#、VB.NET和JScript.NET,到Longhorn发布时,其他兼容.NET的语言也将被包括进来,目前只能使用这三种语言是因为XAML文件的源码需要在运行期解析编译,因此编译器及相关的代码文档对象模型必须在之前就绪(注:如果你完全使用程序代码来编写程序,你可以使用任何.NET语言,但基于XAML的程序目前只能使用这三种而已)。如果XAML Page中嵌入了程序代码,那么你必须先编译才能运行它。而如果在XAML Page中没有程序代码,那么双击就可以显示它,就像Html文件一样。Longhorn不会执行未编译的程序代码,也不会在运行期编译它。
那么,让我们来看看Longhorn版的“Hello World!”吧,这是个最简单的XAML的例子:
<Canvas
xmlns="http://schemas.microsoft.com/2003/xaml"
Background="LightCyan"
Width="100%" Height="100%">
<Image Source="lh.bmp" Canvas.Left="5" Canvas.Top="5" />
<Text Canvas.Left="90" Canvas.Top="20" FontSize="36">Hello, Longhorn!
</Text>
</Canvas>
把这段代码保存在文本文件中并用.xaml作为扩展名,然后双击,用浏览器打开它,图一是你可以看到的结果。<Canvas>节点定义了程序的用户界面区域--画布。Background属性定义了画布的背景色,Width和Height指定了画布的大小,<Image>和<Text>元素定义了该Page的内容。这两个元素的Left和Top属性指定了它们相对于Page左上角的绝对位置。
图一、Simple XAML Page
二、理解Longhorn应用程序
Longhorn提供了一系列的框架类,扩展和增强了.NET Framework1.1的功能,这些扩展包括对XAML和新存储子系统的支持、应用模型、可信赖计算及高级Web服务等。在微软的计划中,Longhorn和Whidbey代表了两个不同的里程碑,Whidbey将在Longhorn发布的前几个月发布,当Longhorn发布时还将发布一个Whidbey的升级版本以提供Longhorn的核心服务。
让我们再来看看所有Longhorn应用程序的公共基础-XAML语言。XAML语言是一种基于XML的语言,用于描述程序的用户界面。熟悉Wind32或.NET Framework编程的开发人员可以马上看出XAML和传统的Windows控件的相似之处。不过,比起Wind32控件和Windows的窗体控件,XAML的标签更加抽象和广泛。想想ASP.NET页面,或者,更具体一点,你可以想像一个只有服务端控件(runat="server“)ASP.NET页面,这跟XAML Page有点类似了。
每个XAML标签都对应一个.NET框架类,包括很多的方法,属性,事件。你可以直接通过XAML标签来设置属性,编写事件,也可以在Code-Behind代码来完成这部分工作。在程序运行期,每个标签对应的控件被实例化并将输出显示在画布中。从最高层的抽象看这个模型跟ASP.NET非常像,只不过这个模型可以工作在更加广泛的整个Windows平台中,而不像ASP.NET仅限于Web程序。
每个XAML标签都对应一个.NET框架类,不过也有很多类没有对应的XAML标签,这些大部分是用于继承的抽象类。任何用XAML创建的东西都可以用程序代码来创建,比如用XAML创建一个按钮,你可以使用下面的脚本:
<Canvas xmlns="http://schemas.microsoft.com/2003/xaml">
<Button Canvas.Left="10"
Canvas.Top="10"
Width="90px"
Height="32px">Click Me</Button>
</Canvas>
你也可以使用下面的C#代码创建一个一摸一样的按钮:
Button btn = new Button();
btn.Width = new Length(90);
btn.Height = new Length(32);
Canvas.SetTop(btn, new Length(20));
Canvas.SetLeft(btn, new Length(75));
btn.Content = "Click Me";
在XAML中你不能使用方法,但是你可以设置属性(Attributes)。XAML中的Attributes对应类的Properties,不过有些Properties并没有对应的Attributes,你可以使用样式表来设置这些Properties。样式表(Styles)是一系列样式属性(style attributes)的集合,编译器会自动把这些样式应用到于样式表关联的控件上。所有的XAML Page都至少有一个Panel元素,做为窗体容器,并控制子控件的位置和背景色、字体这样的全局属性。XAML元素是按树状组织的,只有一个根节点。一般来说,这个根节点是一个panel、border或者canvas。Canvas元素用于根据绝对坐标来绘制内容。一般来说每个元素都被绘制在不同的位置,但也有可能两个以上的元素被绘制在相同的坐标上,这种情况下元素在XAML文件中的出现顺序将决定它们的绘制顺序。
另外,XAML元素还支持大量的事件,通过创建事件处理器,你可以让你的Page动态响应各种事件。给XAML元素创建事件处理器的方法与在ASP.NET中的方法几乎是一样的。事件处理器通过一个属性来声明,:
<Button Width="90px" Height="25px" Click="OnHandleClick">
Click Me
</Button>
Page中的元素构成了应用程序的结构树,这是一个封装了所有运行期组件的对象模型,并且是我们可以通过代码来访问的。在对象模型中,每个控件都提供了访问它在结构树中的子项的方法,主要的模式是:panel.Children.Add(element), listbox.Items.Add(object), button.Content = object和textbox.TextRange.Text = string.控件的子项可以是任意的对象-strings, elements,或者是一些更加复杂的对象(这种时候可能要调用ToString方法)。控件也有一个Parent属性用以访问它在结构树中的父项。通过对象模型,你可以自如地操纵XAML元素。它同时也提供给你一些无法通过XAML实现的功能,比如根据运行环境动态创建元素。
为了把这搞得更明白一些,让我们看看第二个例子。这个例子比“Hello World”复杂一些,我们将在程序中处理一些事件。我之前已经提到过,一个规范的Longhorn应用程序是包括XAML脚本和Code-Behind代码的。下面列出了这个例子的所有代码,这里XAML已经被绑定到Code-Behind代码了。
<!-- XAML file:events.xaml -->
<Window
xmlns="http://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
def:Class="Application1.Window1"
def:CodeBehind="Window1.xaml.cs"
Text="Application1" Visible="True"
>
<DockPanel xmlns="http://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition" def:Language="C#" Background="White">
<FlowPanel ID="sourceFlowPanel"
MouseLeftButtonDown="OnLeftMouseDown"
Margin="10,10,0,0" Background="cyan" Width="150px"
Height="150px">
<Text ID="caption" Margin="10,10,20,20" FontSize="16">Click on
Me</Text>
</FlowPanel>
</DockPanel>
</Window>
// C# Codebehind class file: events.xaml.cs
using System;
using MSAvalon.Windows;
using MSAvalon.Windows.Input;
using MSAvalon.Windows.Controls;
using MSAvalon.Windows.Documents;
using MSAvalon.Windows.Navigation;
using MSAvalon.Windows.Shapes;
using MSAvalon.Windows.Data;
namespace Application1
{
public partial class Window1 : Window
{
private bool expanded = false;
private void OnLeftMouseDown(object sender, MouseButtonEventArgs e)
{
if (expanded)
{
sourceFlowPanel.Width = new
Length(sourceFlowPanel.Width.Value/2);
sourceFlowPanel.Height = new
Length(sourceFlowPanel.Height.Value/2);
caption.TextRange.Text = "Click on Me";
expanded = false;
}
else
{
sourceFlowPanel.Width = new Length(2 *
sourceFlowPanel.Width.Value);
sourceFlowPanel.Height = new Length(2 *
sourceFlowPanel.Height.Value);
caption.TextRange.Text = "Thanks for clicking";
expanded = true;
}
}
}
}
图二 XAML Plus Procedural Code
把XAML解决方案和ASP.NET的Web Form比较一下,除了语法不同外,很难找到其他明显的区别了。def:CodeBehind 和def:Class元素指定C#代码的方法和ASP.NET中的方法也是非常相似的。但是如果你现在用浏览器打开events.xaml,会出现如图3所示的运行期错误。幸运的是,错误信息很清楚,原因是因为XAML不能被动态编译造成的。和ASP.NET不同的是,当XAML脚本中嵌入或引用了程序代码,Longhorn要求先编译才能运行。这个特性和可能会在未来的版本中被修改掉,但在目前,这迫使你必须使用Visual Studio来管理和构建Longhorn程序的项目文件,或者,还有一个选择就是去熟悉MSBuild工具。Longhorn程序项目文件的扩展名、文件结构与Visual Studio 2003中是一致的,见图4。
图三 XAML Error
<Project DefaultTargets="Build">
<PropertyGroup>
<Property Language="C#" />
<Property DefaultClrNameSpace="LonghornApp" />
<Property TargetName="Events" />
</PropertyGroup>
<!--Imports the target which contains all the common
targets-->
<Import Project="$(LAPI)\WindowsApplication.target" />
<ItemGroup>
<!-- Application markup -->
<Item Type="ApplicationDefinition"
Include="eventsApplication.xaml" />
<!-- Compiled Xaml Files list -->
<Item Type="Pages" Include="events.xaml"/>
</ItemGroup>
</Project>
图四 Longhorn Project File
<Import>标签指明了项目的引用信息,<Project>标签指明了编译器生成的包的类型。项目的属性和Item被包裹在<ProjectGroup>和<ItemGroup>标签中。元素的名称都有很好的可读性。你可以在命令行中使用MSBuild来生成可执行文件:
msbuild.exe Events.proj
msbuild.exe在.NET Framework的目录:Windows\ Microsoft .NET中,不过你不用过于关注这个工具,在Whidbey版的Visual Studio中,你只要点击工具条的按钮或按下F5就可以完成这件事情。图5显示了图2代码的运行结果。你只看到一个蓝色的Panel和一些文字,是不是觉得过于简单?其实比你看到的稍微复杂一点。这个程序结构树的根节点是一个DockPanel对象,这是所有UI元素最外层的容器,它包括一个子项,一个FlowPanel,这是上面那些文字的容器,而文字其实是Text类的一个实例。你应该注意到了XAML标签有一些属性用来控制他们的显示,比如Width、Height、Background等。更重要的一点,它们支持ID属性,ID被用作运行期的标识。当你在FlowPanel控件内的任何区域按下鼠标,和FlowPanel关联的MouseLeftButtonDown事件将被触发,这时事件处理器OnLeftMouseDown就被调用,在OnLeftMouseDown中FlowPanel的宽度和高度被设为原来的两倍。再次点击鼠标,FlowPanel又恢复为原来的大小了。
图五 Running the App
虽然你也可以完全使用程序代码比如C#来编写你的程序,但XAML文件使用户界面的描述和模板化变得简单多了。
<未完待续>
如需转贴,请注明作者和出处。