竞争接口
Avalon 是下一版本的 Windows(代号 "Longhorn")的一部分,主要由添加到 .NET 框架中新的类集合组成。目前,用于 Avalon 编程的最重要的新命名空间有多个名称,例如,MSAvalon.Windows、MSAvalon.Windows.Controls 和 MSAvalon.Windows.Media。(在 Longhorn 最终发布之前,这些名称将进行更改。)有了 Avalon,您就可以利用 C#、Visual Basic® .NET 或者任何其他支持 .NET 公共语言规范 (CLS) 的语言编写应用程序。这些程序与目前可编写的 Windows 窗体应用程序颇为相似。即,Avalon 的标准部分。
另外,Avalon 还会定义一个可在 Longhorn 中使用的新标记语言,其代号为 "XAML"(可扩展应用程序标记语言,读作 "zammel")。可以使用 XAML 来定义文本、图像和控件的布局,这与使用 HTML 非常相似。因为基于 XML,所以 XAML 的语法比 HTML 更严谨、更明确。预计大部分的 XAML 均可通过可视化设计程序由计算机生成,但是(最初)手工编写自己的 XAML 会是一次绝佳的学习体验。
大多数写入 Avalon 的应用程序均可能同时包含程序代码和 XAML。您将使用 XAML 定义应用程序初始的可视界面,并编写用于实现其他功能的代码。您可以将程序代码直接嵌入到 XAML 中,也可以将它保留在一个单独的文件内。能够用 XAML 实现的所有功能均可以通过程序代码实现。因此,根本无需使用任何 XAML 也有可能编写程序。但是,反之则不行;许多任务只能通过程序代码完成,因此,只有最简单的应用程序才会只包括 XAML。下面是某个 XAML 的一小段代码:
<Button Background="LightSeaGreen" FontSize="24pt"
Calculate
</Button
该片断是一个 XML 元素,包括一个开始标记、一个结束标记以及这两个标记之间的内容。该元素的类型是 Button。开始标记还包括了两个属性规范;这两个属性的名称为 Background 和 FontSize。它们被指定了属性值,根据 XML 的要求,这些值必须用单引号或双引号引起来。开始标记和结束标记之间是元素内容(在本例中是显示在按钮表面上的文本)。
此 Button 元素不包括宽度或高度。通常,Avalon 中的按钮和其他控件会根据其内容自动调整大小。(当然,您可以重写该行为。)在本例中,Button 的大小被设置为足以容纳 24 磅字体的 "Calculate" 文本字符串。此 Button 元素也不包括坐标位置。通常,控件在运行时会根据窗口和控件的大小在窗口中动态定位。
XAML 与 Avalon 类库紧密相关:可以在 XAML 中使用的每种元素实际上都是一个类,特别是,在 MSAvalon.Windows 命名空间中声明的 UIElement 或 ContentElement 类的子代。Control 是 UIElement 的子代之一,所有公共用户接口控件(例如,按钮、滚动条、列表框、编辑字段等)均源自 Control。从 ContentElement 派生的类包括 Bold 和 Italic。
在 XAML 开始标记中指定的属性名实际上是这些类的属性。属性在 .NET 框架中总是扮演着重要的角色,而在这里扮演的角色则更为重要。如果您还没有任何 .NET 框架的编程实践,也应该知道属性是类的成员,就像方法和字段一样。在使用过程中,它们好象与字段相似,但是它们的实现更接近于方法。不同于字段,属性是包含代码的。属性是可读的、可写的或二者兼有。一个名为 Background 的读/写属性基本上等同于 set_Background 和 get_Background 这一对对称方法。
当然,现代的程序员希望知道:我是否可以将自己的类用作 XAML 元素?答案是:当然可以。出于某种原因,XAML 被称为可扩展应用程序标记语言。任何一个具有公共的无参数的构造函数以及可设置属性的类均可在 XAML 中使用。
我刚才展示的 Button 元素相当于一段完成以下操作的代码:创建一个 Button 类型的对象,然后对 Background、FontSize 和 Content 属性进行赋值。等效的 C# 代码如下所示:
Button btn = new Button();
btn.Background = Brushes.LightSeaGreen;
btn.FontSize = new FontSize(24, FontSizeType.Point);
btn.Content = "Calculate";
正如您所看到的那样,在 XAML 中定义该对象大大简化了对这三个属性赋值的过程。Brushes 类由所有预定义颜色(与 HTML 中通常支持的颜色相同)的静态属性组成。FontSize 是一个结构,其中封装了独立于单位的度量。FontSizeType 是一个枚举。无论属性被定义为字符串、整数、浮点值、布尔值、枚举还是某种其他类型,等效的 XAML 属性都只是被赋予一个文本字符串。
Content 属性指出在按钮表面上显示的内容,并与 XAML 中 Button 元素的内容相对应。这表明还可以按以下方式编写 Button 元素:
<Button Background="LightSeaGreen" FontSize="24pt" Content="Calculate"
</Button
因为此 Button 元素设置了 Content 属性,而且在它的开始标记和结束标记之间不再包括任何内容,所以可将它写为空元素标记:
<Button Background="LightSeaGreen" FontSize="24pt" Content="Calculate" /
注意该元素结尾处的结束斜杠。
在本例中,Content 似乎是 string 类型的属性,但这并不是问题的全部。Content 属性声明为类型对象,强烈建议按钮的内容不必局限于简单的文本字符串。例如,它可以是 Image 元素:
<Button <Image Source="Calc.jpg"/ </Button
如果您希望自己的按钮既显示文本又显示图像,则可以包括:
<Button
Calculate
<Image Source="Calc.jpg"/
</Button
文本和图像元素将并排出现。(这样的元素通常是指父 Button 元素的子元素。)Button 元素不支持更复杂的布局特性,但如果需要,它也是可用的。诀窍是将 Button 的内容指定为支持灵活布局选项的 XAML 元素(例如,Text)。下例中的按钮,其内容是一个 Text 元素。该元素中又包含一个图像、一个分行符和一个文本字符串:
<Button FontSize="24pt"
<Text
<Image Source="Calc.jpg"/
<LineBreak/
Calculate
</Text
</Button
LineBreak 元素等同于 HTML 中的 <br。能够显示下方具有文字的图像的按钮更适用于工具栏。您可以用某种斜体文本格式使该按钮更生动一些:
<Button FontSize="24pt"
<Text
<Image Source="Calc.jpg"/
<LineBreak/
Calculate <Italicthis</Italic
</Text
</Button
该示例很好地说明了标记语言中的内容看上去非常自然,但是用代码表示时却相当不方便的一面。实际上,您可以在代码中指定所有这些元素,但是您为什么要这样做呢?
既然您对 XAML 有了一些了解,那么现在就让我们来看一些完整的程序吧。图 1 显示了传统的 Hello World 程序的简单 XAML 实现。在 XML 中只允许使用一个根元素,而在 XAML 中,这个根元素通常是输出图面。TextPanel 是一个输出图面,它提供类似于 HTML 的自动布局。通常,对于应用程序的每一页都有一个 XAML 文件(如果应用程序确实有多个页),而且对于每个对话框也都有一个 XAML 文件。有一个名为 Styles 的功能(我将在以后对此稍加讨论)有助于在您的程序中保持一致的视觉样式。
TextPanel 元素中 xmlns(XML 命名空间)属性的功能与 C# 中使用指令所实现的功能相同。因为 XAML 文件中的所有元素都映射到了 Microsoft .NET 框架中的等效类,所以 xlmns 属性提供了一个指向某个文件的 URI,该文件会列出在其中声明这些类的 .NET 命名空间的名称。
仅仅为了使 Hello World 程序更加吸引人,我向 TextPanel 元素中添加了几个属性来设置颜色和字体,并指定该元素的子元素在面板中水平居中。TextPanel 元素的内容是字符数据 "Hello, world!",其内容中还可以包括图像、控件、更多的文本等。
由于其中没有代码,因此您可以将 HelloWorld.xaml 文件直接加载到 Microsoft Internet Explorer 的 Longhorn 版本中,然后您将看到类似于一个 Web 页的内容。还可以使用一个目前称作 MSBuild 的程序来编译 HelloWorld.xaml。进行这种编译时,还需要两个其他的短文件(此处未显示)。其中一个扩展名为 PROJ 或 MSPROJ 的文件会提供有关该程序的一些信息并列出所有必需的源文件(XAML 以及其他文件)。还需要另外一个 XAML 短文件来指出执行该程序时首先显示哪个 XAML 页。运行 Hello World 的可执行文件,您将看到一个类似于 Windows 程序的内容。图 2 同时显示了这两个版本。
图 2 Hello World 作为页面和作为程序
图 3显示了与此程序几乎等效的 C# 版本。(我之所以说几乎等效,是因为 MSBuild 能够抛出 C# 代码,但是这不是它所抛出的全部内容。我的版本更容易理解一些。)您可以按照以下方式,在命令行上编译该程序:
csc /r:WindowsBase.dll;PresentationCore.dll;PresentationFramework.dll
有经验的 Windows 窗体用户会发现该程序的结构和外观似乎有些熟悉。该程序负责在创建 TextPanel 对象之前,显式创建一个应用程序对象和一个窗口对象。在该程序的 XAML 版本中,这些预备作业是隐含的。
此 C# 代码的奇怪之处涉及到在窗口中显示的文本字符串。在 Windows 程序中,通常需指定要显示文本的坐标位置,但是 Te