您的位置:首页 > 编程语言

[转]使用新的代码和标记模型创建真实的应用程序

2005-08-23 18:00 423 查看
Charles Petzold
本文内容基于 PDC 召开之前 Microsoft Windows 代号为 "Longhorn" 的版本,此处包含的所有信息均可能更改。
下载本文的代码:Avalon.exe (141KB)
注:本文是在产品的发行版投入生产之前完成的,因此,我们不能保证这里包含的任何细节与发行产品中找到的细节完全一样。文中对产品的描述信息仅限于本文发表时的产品,并且仅用于规划方面的用途。本文的信息随时可能更改,恕不预先通知。
摘要 下一个版本 Windows(代号 "Longhorn")中的表示子系统为开发人员提供了强大的新功能。这个子系统(代号 "Avalon")使开发人员能够通过新的标记语言代码(代号 "XAML")来使用它的功能。另外,面向对象的现代编程语言(例如,C# 和 Visual Basic .NET)可用于将所有内容联系在一起。因为写入 Avalon 的大多数应用程序都有可能是 XAML 和编程代码的混合体。所以本文将讨论用于控制页面布局的 XAML 标记,以及为了响应事件而编写的过程代码。


几千年来,哲学家和科学家一直尝试用二元论原理(对立但又共存)来解释宇宙:善与恶、阴与阳、物质与能量、精神与肉体、波与粒子,当然还包括编程代码与标记语言。目前,编程与标记在不稳定的休止状态中共存。在理论上,编程语言可完成计算机能够完成的任何事情,但是常常无法灵活地完成以下任务:在简单的可视界面中布置文本、图像和控件。标记更适于定义那些能适应不同屏幕大小和环境的、结构复杂的文本和图像页。但是,如果通过迥异的方式与用户进行交互,就绝对不是一个好的选择。
在创建新的用于构建基于 Windows® 的客户端应用程序的编程接口时,Microsoft 的开发人员已经决定不拒绝这种二元论,而是接受并赞扬它。他们已经创建了一个环境 — 在这里,编程和标记以互相支持的角色明显地混杂在一起。其结果,诞生了代号为 "Avalon" 的表示子系统,这可能是自“亚当和夏娃”以来在协同二元论中最伟大的体验。差异万岁!

竞争接口

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 <Italic>this</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 程序中,通常需指定要显示文本的坐标位置,但是 TextPanel 包括的自动布局功能会根据窗口的大小以及内容来排列面板的内容。这是 HTML 现在已经对客户端应用程序编程产生影响的一种方式:有了 Avalon,您就可以在编程代码中使用自动布局了。


返回页首

布局选项

XAML 文件的根元素通常是显示其他元素的图面。为此,Avalon 包括一个 Panel 类以及 Panel 的几个子代,其中包括在 HelloWorld 中使用的 TextPanel 元素。
FlowPanel 类似于 TextPanel。与 HTML 一样,FlowPanel 和 TextPanel 都会根据元素和窗口的大小进行自动布局。TextPanel 具有更复杂的文本格式设置功能,甚至可以将文本排列到多列中。如果不需要大量的文本格式设置,FlowPanel 则是更加高效的选项。
如果您希望在 HelloWorld 程序中使用 FlowPanel,将必须更改指定的在面板上显示文本的方式。与 TextPanel 不同的是,FlowPanel 不允许使用文本内容,但是它允许使用由 Text 元素组成的内容。最好使用一个 Text 元素,并将 FontFamily 和 FontSize 属性移动到该元素中:
<Text FontFamily="Comic Sans MS" FontSize=36pt>Hello, world!</Text>
另一个面板选项是 DockPanel,它以平铺方式排列它的子元素,并将它们固定到面板的边缘。Windows Explorer 是使用停靠功能的应用程序的典型示例;顶部有一个工具栏,底部有一个状态栏,左侧是目录树,右侧是目录内容。
GridPanel 按行和列排列子元素。Avalon 还提供了一个 Table 控件,该控件提供类似于 HTML 表的附加功能。
最后一个布局选项是 Canvas,该选项中已不再包括笛卡尔坐标系统的扇形。您需要使用为该目的而提供的属性在 Canvas 面板上显式定位元素。
在一个页上不再限制只使用一个面板。XAML 中的所有内容都是分层的。例如,您可以使用 DockPanel 将一个页面分为三个区域,然后对于这三个区域使用 FlowPanel、Canvas 和 GridPanel:
<DockPanel>
<FlowPanel DockPanel.Dock="Left">
•••
</FlowPanel>
<Canvas DockPanel.Dock="Top">
•••
</Canvas>
<GridPanel DockPanel.Dock="Fill">
•••
</GridPanel>
</DockPanel>
标记语言之所以比编程代码更适于定义可视界面,XAML 的分层特征是其中一个原因。标记语言可以用嵌套和缩进来模仿层次结构。实际上,在 1985 年首次引入 Windows 1.0 时,程序员就使用文本资源脚本来定义其菜单和对话框的分层结构了。此时,层次结构只是向深层更进了一步,但这只是个开始。XAML 文件仅仅是资源脚本。
Button 元素的内容可以是文本、图像,或者是嵌套的 Text 元素中文本和图像的组合。Button 的内容还可以是放置其他元素的面板。 4 显示了一个名为 SmileyButton 的程序,该程序可完全执行上述操作。此按钮的内容是一个 Canvas。然后该程序会将 MSAvalon.Windows.Shapes 命名空间中的几个元素放到 Canvas 上。 5 显示了正在运行的程序。



5 操作中的 SmileyButtonShapes 命名空间包括一个名为 Shape 的抽象类和七个子代:Line、Polyline、Rectangle、Ellipse、Polygon、Glyphs 和 Path。遗憾的是,在 Shapes 命名空间中没有 Arc 或 Bezier 类,因此我将嘴巴绘制成了一个两段的折线。我本来可以在 Path 元素中使用贝塞尔曲线模仿一段弧线,但是不会显示出来。您可以利用 XAML 页内附加的编程代码绘制更多的图形。


返回页首

事件处理

基于 Windows 的应用程序不仅仅是为了显示 Web 页,它们需要以非常专门的方式响应用户界面事件。这种情况下,必须由实际的编程代码对 XAML 进行补充。您可以将这种代码放到单独的文件中,也可以将其直接嵌入到 XAML 中。在本文中,为简单起见,我将演示后一种方法。
.NET 框架和 C# 有一个名为事件的通用机制,类之间使用事件来互相发出信号。事件是类的成员,就像方法、字段和属性一样。一个类声明一个事件。然后另一个类可以选择为该事件安装事件处理程序,事件处理程序只是一种具有特定签名和返回类型的方法。第一个类随后可通过调用该方法向第二个类发出信号。事件总是与委托相关联,委托本质上是方法原型。事件处理程序必须按照该委托来声明。
用户界面的原型事件是按钮单击。Button 类有一个名为 Click 且与 ClickEventHandler 委托相关联的事件,该委托要求按以下方式声明 Click 的事件处理程序:
void ButtonClick(object el, ClickEventArgs args)
{
MessageBox.Show("The button has been clicked");
}
为了指明某个元素,我将第一个参数的名称赋值为 el。在 XAML 中,您应将事件处理程序的名称指定为 Button 元素的某个属性:
<Button Click="ButtonClick" ...>
将该编程代码嵌入到 XAML 文件中需要使用一些特殊语法。编程代码通常包括一些符号(例如 < 和 &),这些符号在 XML 中具有特殊含义。XML 规范包括一个名为 CDATA 节的功能,其目的完全是为了在 XML 文件中包括任意字符数据。XAML 文件中的任何编程代码都必须括在 CDATA 节中。CDATA 节总是以字符串 "<![CDATA[" 开头,并以字符串 "]]>" 结尾。在任何情况下,字符 "]]>" 都不能出现在 CDATA 节中。实际上,如果您编写类似下面的 C# 代码,就会出现问题:
if (arr1[arr2[I]]>5)
只需在无意输入的 CDATA 分隔符 ("))>") 中的某个位置插入几个空格,即可使一切正常。 在 XAML 中,CDATA 节还必须用 def:Code 元素括起来,还有一些其他元素必须指出所使用的编程语言。(此时,您可以使用 C#、Visual Basic .NET 和 JScript® .NET。) 6 显示了一个完整的 XAML 文件,其中包括一个按钮以及一个由嵌入的 C# 代码处理的 Click 事件。必须对该文件进行编译,因为 Internet Explorer 的 Longhorn 版本不能解释 C# 代码。单击该按钮,即会弹出一个消息框。


返回页首

元素和对象

如果页面上有多个按钮,则可以对于每个按钮使用不同的事件处理程序。只需给它们指定不同的名称。一个事件处理程序页可以为多个按钮提供服务。如果是这样,该处理程序通常必须完全确定按下了哪个按钮。对于此问题有几个解决方案。
首先,请注意,Click 事件处理程序有两个参数。第一个参数是生成该事件的对象。在本例中,它是用户单击的特定 Button 对象。在该事件处理程序中,可以将该参数强制转换为 Button 类型的对象:
Button btn = el as Button;
然后,您可以继续访问 Button 类的所有成员。您可以更改按钮的颜色,可以更改文本,或许还可以禁用该按钮,或者甚至还可以设置另一个事件处理程序。
FrameworkElement 类(所有的控件和面板都从该类派生)包括一个非常特殊的属性,该属性的名称为 ID,其类型为字符串。您可以将该属性设置为用于标识按钮的文本字符串。MSBuild 要求一页上的所有 ID 值都是唯一的。下面的两个 Button 元素具有相同的事件处理程序,但还包括了下列 ID 属性:
<Button ID="OkButton" Click="ButtonClick">OK</Button>
<Button ID="CancelButton" Click="ButtonClick">Cancel</Button>
在该事件处理程序中,可以使用 ID 属性来区分不同的按钮,这或许可以通过一个 switch 语句来完成:
switch(el.ID)
{
case "OkButton":
•••
break;
case "CancelButton":
•••
break;
}
这是使用 ID 属性的一种方法。但是,正如我以前说过的那样,ID 属性确实非常特殊。 让我们再看一下下面的两个 XAML 元素:
<Button ID="OkButton" Click="ButtonClick">OK</Button>
<Button ID="CancelButton" Click="ButtonClick">Cancel</Button>
当 MSBuild 将该 XAML 转换为 C# 代码以准备进行编译时,它还创建两个类型为 Button 的字段,这两个字段的名称为 OkButton 和 CancelButton。这些字段被设置为与已创建的 Button 对象等同。在该事件处理程序中,可以像使用 Button 对象那样使用这些 ID 名称。例如:
if (el == OkButton)
{
•••
}
else if (el == CancelButton)
{
•••
}
我在此处使用的是 if 语句,而不使用 switch,这是由于 switch 只允许使用整数和字符串表达式。 不仅可以使用这些 ID 名来区分不同的对象,而且可以显式访问页面上的所有其他元素 — 或者至少可以访问已经被赋予了 ID 值的元素。例如,某个其他控件可能希望根据它所确定的布尔值来启用或禁用 OK 按钮。它就像下面的代码一样简单:
OkButton.IsEnabled = bEnable;
实际上,事件处理程序可以访问页面上的任何元素(甚至是那些不具备 ID 属性的元素),原因在于这些元素通过一个元素树全部链接在一起。我在前面讨论过元素如何支持子级。ILogicalTreeNode 接口(由 FrameworkElement 类实现,因此也由充当元素的许多类来实现)定义了两个名称分别为 Parent 和 Children 的属性。使用这两个属性,您可以访问整个元素树,因此能够向该树动态添加元素、从该树内删除元素或者对该树进行更改。
7 显示一个名为 MoveButtons 的程序,该程序具有三个标记为 "Tom"、"Dick" 和 "Harry" 的按钮。无论单击哪个按钮,该按钮都会在另外两个按钮之间移动,这只需通过在面板的 Children 属性中变换元素即可完成。您能想象出等效代码在简单的 Win32® 或 MFC 程序中(或者甚至在 Windows 窗体应用程序中)的外观吗?


返回页首

动画

除了很明显的 GIF 动画文件以外,图形动画几乎总是涉及到代码。因此,XAML 一个最令人惊奇的方面就是一个可完全使用标记语言的完整动画工具。不论好坏,均可以相当方便地将几个动画效果嵌入到 XAML 页中。
要了解如何使用该工具,必须首先了解用于在开始标记中设置元素属性的替换方法。元素
<Button Background="Red">
Cancel
</Button>
还可以写为以下形式:
<Button>
Cancel
<Button.Background>
Red
</Button.Background>
</Button>
Background 属性现在是一个用 Button 元素括起来的独立标记,该属性的值现在被指定为 Button.Background 标记的内容。我将对该属性进行动画处理。将该内容替换为 ColorAnimation 元素,如下所示:
<Button>
Cancel
<Button.Background>
<ColorAnimation From="Red" To="Blue"
Duration="10" Fill="Hold"/>
</Button.Background>
</Button>
现在,当该按钮第一次显示时,颜色会在一个 10 秒钟的过程中从红色变为蓝色。实际上,它并不是特别简单:因为 Background 属性未被定义为 Color,而是被定义为 Brush,所以您必须包括一个 SolidColorBrush 元素并将它作为 Button.Background 的子元素,还必须包括一个 SolidColorBrush.ColorAnimations 元素并将它作为 SolidColorBrush 的子元素。随后 ColorAnimation 元素成为 SolidColorBrush.ColorAnimations 的子元素,如下所示:
<Button>
Cancel
<Button.Background>
<SolidColorBrush>
<SolidColorBrush.ColorAnimations>
<ColorAnimation From="Red" To="Blue"
Duration="10" Fill="Hold"/>
</SolidColorBrush.ColorAnimations>
</SolidColorBrush>
</Button.Background>
</Button>
此方法较为笨拙,但是在对渐变和其他复杂的画笔进行动画处理时灵活性较高。使用 Brush 背景,甚至可以引进诸如图像和视频之类的丰富背景。
当然,还有许多动画选项。您可以(根据重复次数或时间)指定动画重复,并指出动画在每次重复之后进行翻转。您还可以指定加速和减速。如果要对动画进行更多的控制,甚至可以提供一系列关键值和关键时间以及内插方法。
您还可以对浮点值、坐标点、尺寸和 Length 值进行动画处理。 8 中的 AnimationButton 程序类似于 SmileyButton,不同之处在于它对左眼的一个轴进行了动画处理,使其看上去像是在眨眼睛。


返回页首

样式

有时,您会发现自己要为一组相关的控件设置相同的属性。如果是使用 HTML,则可以使用级联样式表 (CSS) 来帮助进行设置。在 Avalon 中,则可以使用 Style 元素执行相似的操作。例如,如果您希望 FlowPanel 上的每个按钮的背景都为青色,字体都为 14 磅,则可以包括一个如下所示的 Style 标记:
<FlowPanel.Resources>
<Style>
<Button Background="Cyan" FontSize="14pt"/>
</Style>
</FlowPanel.Resources>
在同一个 Resources 区域中可以指定多种元素,并对于每种元素类型都使用一个 Style 元素。还可以指定希望将样式应用于从特定元素派生的所有类、具有某个 ID 值的所有类或者不具有某个 ID 值的所有类。
还可以赋予某个样式一个名称并将该样式只应用于某些元素。例如,假设一个对话框有多个单选按钮,您希望其中的某些单选按钮具有不同的大小、颜色或者任何其他属性。对于这些单选按钮,可以分配一个特定的 Style:
<RadioButton Style="{Special}" •••>
在下面的 Style 声明中,第一个样式应用于那些将 Style 指定为 "{Special}" 的单选按钮,第二个样式应用于那些未设置 Style 属性的单选按钮:
<FlowPanel.Resources>
<Style def:Name="Special">
<RadioButton •••/>
</Style>
<Style>
<RadioButton •••/>
</Style>
</FlowPanel.Resources>
对于属性表来说,甚至还可以通过某种方法来指定某些属性,使其只应用于已设置其他属性的元素。


返回页首

Avalon ColorScroll

9 显示了一个名为 ColorScroll.xaml 的程序,该程序包括本文中讨论的许多 Avalon 功能。ColorScroll 是一个简单 Windows 程序的 Avalon 版本。这个简单程序最初刊登在 1987 年 5 月出版的 Microsoft Systems Journal(本杂志的前身)中,而且还出现在我撰写的《Programming Windows》一书的各个版本中。最近,在我的《Programming Microsoft Windows with C#》(Microsoft Press® 于 2001 年出版)和《Programming Microsoft Windows with Microsoft Visual Basic .NET》(Microsoft Press 于 2002 年出版)两本书中,我将该程序转换为 Windows 窗体程序。
10 显示了该程序在操作时的情况。对该程序左侧的三个滑块进行操作,以便根据红色、绿色和蓝色等原色来选择颜色。这些原色的值显示在滑块的下面,最终的颜色显示在窗口的右半部分。在调整窗口的大小时,滑块会随窗口的总宽度和总高度自行调整。
在使用 Windows API 或 Windows 窗体编写这样的程序时,所面临的一些挑战将涉及移动窗口中的所有组件以及调整它们的大小,而这正是 Avalon 的价值所在。



10 操作中的 ColorScroll主面板是一个 DockPanel 元素。两个子元素各占父元素的一半宽度。左侧是一个 FlowPanel,右侧是一个 TextPanel。TextPanel 负责显示颜色,TextPanel 被赋予 ColorPanel 的 ID 值。
左侧的 FlowPanel 有三个 DockPanel 子元素,每个子元素都占父元素的三分之一宽度。其中的每个 DockPanel 元素又都有三个子元素:两个Text 元素(分别位于顶部和底部),一个 Slider 元素(位于中间)。
Text 和 Slider 元素的尺寸在该文件开始部分的 Style 元素中提供。Text 字体的大小设置为 12 磅,Text 元素的高度是 36 磅。文本在 Text 元素中垂直居中,因此,这些额外空间可在文本周围提供一些区域,使其看上去很自然。因为这两个 Text 元素分别停靠在 DockPanel 的顶部和底部,所以它们占据了父元素的全部宽度,每个 Text 元素的宽度都是窗口总宽度的六分之一。
三个 Slider 元素分别填充每个 DockPanel 的中间部分。但是,属性表将每个滑块的宽度指定为其父元素的 50%。而且,在左侧和右侧提供的边距宽度分别为其父元素的 25%。这些边距在滑块的两侧提供了另一个空白区域,使得滑块看起来不是那么拥挤。
除了 Text 框的字体大小和高度以外,所有的尺寸都是以相对于窗口宽度的百分比提供的。当然,这需要费些脑筋,但是比用像素确定尺寸容易得多。
每个 Slider 元素都包含几个必须以相同方式初始化的属性。每个滑块的范围都是从 0 到 255。箭头键会以 1 为单位滚动;按向上翻页或向下翻页键,或者单击滑块的中央区域会以 16 为单位滚动滑块。这些属性均包括在了样式规范中。(也许,一个更好的方法是从已经包括两个 Text 元素和一个 Slider 元素的 DockPanel 派生一个新类,然后为红色、绿色和蓝色滚动条创建该类的三个对象。)
这三个滚动条的 ID 值分别为 RedScroll、GreenScroll 和 BlueScroll;窗口右侧的 TextPanel 的 ID 值为 ColorPanel。在滑块的 ValueChanged 事件的 OnScrolled 事件处理程序中,会引用所有这些 ID 值。
事件处理程序首先执行某个巧妙的操作:它使用 Parent 属性和面板的 Children 属性来获取引发该事件的特定滑块的前辈。这个前辈就是滑块下面的 Text 元素,该元素显示颜色的数字值。此方法随后将该元素的文本设置为滑块的新值。此方法从传递到事件处理程序的 ValueChangedEventArgs 对象的 Value 属性获取该值,它还可以将该对象的参数强制转换为 Slider 并访问该对象的 Value 属性。
此方法随后根据所有这三个滑块的 Value 属性计算一个新颜色,并使用该颜色来为右侧的 TextPanel 设置新的 Background 属性,该 TextPanel 的 ID 为 ColorPanel。
此程序最近的 Win32 API 版本(在第五版的《Programming Windows》中称为 COLORS1)的长度为 250 行。在《Programming Microsoft Windows with C#》中,Windows 窗体版本的长度大约为 100 行。这个新版本的长度大约只有 60 行,我深信,通过使用继承功能还可以对它进行进一步修剪。
从 250 行到 100 行,直到现在的 60 行,这就是通常所说的进步。


返回页首

结论

Avalon 和 XAML 象征着与过去基于 Windows 的应用程序编程的脱离。在许多方面,设计应用程序的 UI 都将比过去容易得多,而且部署起来也更轻而易举。很明显,由于有了用于 UI 定义的轻量 XAML 标记,基于 Longhorn 的应用程序会成为集中 Web 和桌面编程模型的下一步发展方向,并且会合并上述两种方法的最佳功能。
Charles Petzold 是 MSDN Magazine(及其前身 MSJ)的长期特约编辑,他是 Microsoft Press 即将出版的一本有关 Avalon 图书的作者,这本书的书名暂定为《Programming the Windows Client Platform》。他的 Web 站点是 http://www.charlespetzold.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐