每个 Silverlight 项目都以一小组关键文件开始。所有以 .xaml 扩展名结尾的文件都使用了一种灵活的标记标准 XAML(eXtensible Application Markup Language)。所有以 .cs 扩展名结尾的文件都用来存放运行程序所用的 C# 源代码。
针对上图,下面详细描述主要文件的作用:
- App.xaml 与 App.xaml.cs:它们用于配置 Silverlight 程序。可以让你自定义应用程序所有页面中都能使用的资源,也可以让你对程序事件作出响应。例如,启动、关闭、发生错误时。在一个新生成的 Silverlight 项目中,App.xaml.cs 文件中的启动代码会指定你的应用程序应当从显示 Page.xaml 开始。
- MainPage.xaml:此文件定义了将在第一个页面显示的用户界面(控件集、图像、文本)。从技术上说,Silverlight 页面是一个用户控件(派生自 UserControl)。Silverlight 应用程序可包含任意多个页面。
- MainPage.xaml.cs:此文件包含构建第一个页面的代码,包括用来响应用户动作的事件处理程序。记住,这些事件运行在客户端。
项目中还有更多要素。“属性”节点下的 AppManifest.xml 列出了应用程序所使用的程序集。AssemblyInfo.cs 包含关于项目的信息(名称,版本,发布者)。在编译时,这些信息会嵌入到 Silverlight 程序集里。这两个文件不需要你手工编辑。
设计 Silverlight 页面
每一个 Silverlight 页面都包含用来定义视觉表现的标记(XAML 文件)和定义事件处理程序的源代码文件。要定义第一个 Silverlight 应用程序,只需打开 Page.xaml 文件,然后开始添加标记。
VS 提供了两种查看 XAML 文件的方式。可视化视图(设计视图)或直接显示标记(源代码视图)。
作为起步,我们现在尝试创建如下页面,它定义了一段文本和一个按钮:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="100">
<StackPanel>
<TextBlock x:Name="lblMessage" Text="Hello world." Margin="5"></TextBlock>
<Button x:Name="cmdClickMe" Content="Click Me!" Margin="5"></Button>
</StackPanel>
</UserControl>
运行程序,效果如下:
Silverlight 元素表
类 |
描 述 |
元素类型 |
TextBlock | 文本显示。要为内联文本多个片段进行不同格式化,可加 Run 元素 | 显示文本 |
Image | 显示图像。支持 PNG、JPG,不支持 GIF | 显示图像 |
Button | 按钮控件。有单击事件 | 一般控件 |
TextBox | 文本输入框 | 一般控件 |
PasswordBox | 隐藏用户输入文字的文本框 | 一般控件 |
CheckBox | 复选框 | 一般控件 |
RadioButton | 单选按钮 | 一般控件 |
ListBox | 项目列表 | 一般控件 |
ComboBox | 下拉列表 | 一般控件 |
HyperlinkButton | 超链接 | 一般控件 |
Slider | 一个输入控件,用户可以沿着轨道拖动滑块,从而设定数值 | 一般控件 |
ProgressBar | 一个着色的长条,指明给定任务完成百分比 | 一般控件 |
Calendar* | 日历视图,一次仅显示一个月 | 日期控件 |
DatePicker* | 输入日期的文本框,自带一个下拉日历方便选择 | 日期控件 |
Border | 一个矩形或带圆角的边框 | 简单容器 |
ScrollViewer | 可放置含有大量内容的其他元素,并提供一个可滚动的视图 | 简单容器 |
TabControl* | 将元素分成单独的标签页,一次只能查看一个标签页 | 布局容器 |
StackPaner | 将一组子元素从上到下,或从左到右排放 | 布局容器 |
Canvas | 可使用精确坐标布局一组子元素 | 布局容器 |
Grid | 可将一组子元素排列在隐藏的由一组单元格组成的网格中 | 布局容器 |
GridSplitter* | 一个可调整大小的小块,用户可改变相邻行的高度或相邻列的宽度 | 布局工具 |
Line | 绘制线条 | 简单形状 |
Retangle | 绘制矩形 | 简单形状 |
Ellipse | 绘制椭圆 | 简单形状 |
Path | 绘制几何对象定义的形状 | 简单形状 |
MultiScaleImage | 支持 Deep Zoom 功能,可将大图像缩放到精确位置 | 富控件 |
MediaElement | 媒体文件。音频或视频窗口 | 富控件 |
DataGrid* | 由一组数据对象填充的表格 | 富控件 |
带 * 元素不是核心 Silverlight 运行时的一部分。使用了它们会添加对附加程序集的引用。
Silverlight 附加程序集
Silverlight 架构的初衷就是将核心框架尽可能的小巧以便于下载安装。Silverlight 设计师从核心运行时中移除了一些功能,并放入了独立的附加程序集中。但如果你使用了它们,就需要将它们和应用程序打包在一起,这需要做通盘的考虑(Silverlight 内建的压缩机制会改善这一结果)。
两个常用的 Silverlight 程序集:
- System.Windows.Control.dll:包含一些新的控件,包括 Calendar、DatePicker、TabControl、GridSplitter。
- System.Windows.Control.Data.dll:包含新的、完全从头开始构建的 DataGrid。
理解 XAML
从概念上说,XAML 是一种标记语言,与 HTML 扮演相似的角色。
XAML 文档中的每一个元素都对应 Silverlight 类的一个实例,元素名称与类的名称精确匹配。例如,上例中 <StackPanel> 元素会指示 Silverlight 创建一个 StackPanel 对象;<TextBlock> 会指示 Silverlight 创建一个 TextBlock 对象。
在 XAML 中嵌套元素的方式非常重要!<TextBlock> 只能放在 <StackPanel> 中,且 StackPanel 是一个容器控件,所以 TextBlock 是在 StackPanel 中呈现的。
当在 XAML 文件中使用 <TextBlock> 元素时,Silverlight 解析器会识别出你想要创建 TextBlock 类的一个实例。然而,它无需知道使用的 TextBlock 类是什么。毕竟,即便 Silverlight 命名空间只包含一个单独的名为 TextBlock 的类,但谁也不能保证你不会创建一个自定义的同名的类。换言之,你需要一种方法来指明 Silverlight 命名空间信息,从而使用元素。
在 Silverlight 中,通过将 XML 命名空间映射到 Silverlight 命名空间来解析类。
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="100">
http://schemas.microsoft.com/winfx/2006/xaml/presentation 是核心 Silverlight 命名空间。它包含所有 Silverlight 中的类。通常这个命名空间没有使用命名空间前缀来声明,因此它就成了整个文档的默认命名空间。换句话说,除非你额外指明,否则每一个元素都会被自动放入这个命名空间中。
http://schemas.microsoft.com/winfx/2006/xaml 是 XAML 命名空间。它包含多种 XAML 功能,可以让你控制文档如何被解析,通常会映射到 x 前缀。
我们创建元素时(上例)并没有加入什么前缀,所以使用的就是默认命名空间。Silverlight 就知道创建的元素是它的核心控件,而非你自己创建的类似 StackPanel 这种同名的类。
设置属性
XAML 文档中的每个元素都相当于一个类。同样,在元素中设置的每个属性都相当于设置了 ASP.NET 中的一个属性或事件。
Silverlight 使用类型转换器来将字符串值转为适当的数据类型。可轻松将数值字符串转换为数值,将颜色名称字符串转换为颜色值:
<StackPane Background=”Red”>
然而,你也可能会使用对象设置属性。由于对象不能简单的用单个字符串表示,复杂的属性可以用嵌套元素的语法来处理。嵌套元素使用两段式的名称,其形式为 ClassName.PropertyName 。
例如,下面的标记通过创建 RadialGradientBrush 设置了 StackPanel.Background 属性,这个背景色的设置与上例中有本质的区别。
<UserControl ...>
<StackPanel>
<StackPanel.Background>
<RadialGradientBrush Center="0.5,0.5">
<GradientStop Offset="0" Color="LightSteelBlue"></GradientStop>
<GradientStop Offset="1" Color="White"></GradientStop>
</RadialGradientBrush>
</StackPanel.Background>
<TextBlock x:Name="lblMessage" Text="Hello world." Margin="5"></TextBlock>
<Button x:Name="cmdClickMe" Content="Click Me!" Margin="5"></Button>
</StackPanel>
</UserControl>
XAML 代码隐藏
XAML 可以构建用户界面,但为了实现程序的功能,需要某种方式来关联程序代码的事件处理程序。XAML 使用 Class 属性来简化这一过程:
x 命名空间前缀在 XAML 命名空间中放置了 Class 属性,这意味着 Class 属性是 XAML 语言的更通用的部分,而非某个特定的 Silverlight 组件。事实上,Class 属性告诉 Silverlight 解析器生成一个新类,这个类继承由 XAML 元素命名的类。换言之,这个例子创建了一个新的名为 SilverlightApplication1.MainPage 的类,它继承自 UserControl 基类。这个类里自动生成的部分已经和你在代码隐藏文件里提供的代码组合到一起了。
通常,每个客户端都会有一个用 C# 代码写的代码隐藏类。见下面:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
}
当前,Page 类没有任何实际功能。不过,这个默认的构造函数非常重要,它会在创建类的实例时调用 InitializeComponent(),这可以解析标记,创建相应对象,设置它们的属性,并附加所定义的事件处理程序。不要删除对它的调用,如果添加了新的构造函数,也要调用此方法。
隐藏代码中要访问到前端的控件,则该控件必须包含 Name 属性:
<TextBlock x:Name="lblMessage" Text="Hello world." Margin="5"></TextBlock>
处理事件
可以使用属性来附加事件,只要指定事件处理程序的名称即可。这与 ASP.NET Web 页面中使用的方式类似,不过事件属性不再以 On 开头。
<Button x:Name="cmdClickMe" Click="cmdClickMe_Click" Content="Click Me!" Margin="5"></Button>
虽然不是必需的,但是将事件处理方法命名为 ElementName_EventName 的形式已经是约定俗称的了。
private void cmdClickMe_Click(object sender, RoutedEventArgs e)
{
lblMessage.Text = "Goodbye, cruel world.";
}
你会发现,Silverlight 元素提供了如 WPF 和 Windows Forms 中这类富客户端平台的完整事件集合的一个子集。你能找到大多数你所期待的事件,包括修改事件(TextChanged、SelectionChanged)、键盘事件(KeyDown、KeyUp、GotFocus、LostFocus)、鼠标事件(MouseLeftButtonDown、MouseLeftButtonUp、MouseEnter、MouseLeave、MouseMove)以及初始化事件(Loaded)。
了解 Silverlight 类库
为了编写实际的代码,需要了解更多关于要使用的类的知识,这意味着需要深入领会随 Silverlight 发布的核心类库的详细知识。
Silverlight 包含了源于 .NET 完整框架类的一个子集,虽然不是全部,但同样包含了数量客观的功能。Silverlight 框架通过两种方式简化。首先,它不提供 .NET 框架中所有的类型。其次,它包含的类不会提供全部重载的构造函数、方法、属性和事件。
Silverlight 只保留大多数重要类中最实用的成员,为精简版 .NET 框架留下足够的功能来创建令人注目的代码。
在开始正式的编码前,先浏览一下 Silverlight 版本的 .NET 框架。在 VS 中使用对象浏览器查看下:
- mscorlib.dll:这个程序集之于 Silverlight,就相当于 mscorlib.dll(包含了 .NET 框架中最基础的那一部分) 之于 .NET。Silverlight 版本包括 System 命名空间中的核心数据类型、异常和接口、常规集合和泛型集合、文件管理类以及对国际化、反射、资源、调试和多线程的支持。
- System.dll:包含附加的泛型集合、处理 URI 的类以及处理正则表达式的类。
- System.Core.dll:包含对 LINQ 的支持。
- System.Net.dll:包含了支持网络连接的类,可以让你下载网页,并创建基于 Socket 的连接。
- System.Windows.dll:包含许多构建 Silverlight 用户界面的类,包括基本元素、形状和画笔、支持动画和数据绑定的类以及使用隔离存储的 OpenFileDialog。
- System.Windows.Browser.dll:包含与 HTML 元素交互的类。
- System.Xml.dll:包含需要用来处理 XML 的最简化的类:XmlReader 和 XmlWriter。
Silverlight 程序集中的一些成员仅能用于 .NET 框架代码,而不能用于你的代码调用。这些成员以 [SecutityCritical] 特性标记。例如,Silverlight 应用程序只能通过 隔离存储API 或 OpenFileDialog 类访问文件系统。鉴于此,FileStream 类的构造函数被赋予了 [SecutityCritical] 特性。