Silverlight – 快速指南
Silverlight – 快速指南
Silverlight – 概述
欢迎使用 Silverlight 教程。Silverlight 是用于构建富 Internet 应用程序的平台。本教程将解释 Silverlight 背后的概念,并向您展示如何将它构建到您的 Web 应用程序中。完成后,您将对使用 XAML 和 C# 的 Silverlight 应用程序有更好的了解。
什么是银光
Silverlight 是一个浏览器插件,专为构建丰富的 Internet 应用程序而设计;在浏览器中运行的应用程序就像普通的 Web 应用程序一样,但它们试图将用户界面提升到 HTML 可以达到的范围之外。例如,
-
Silverlight 是一个框架,用于构建在各种操作系统上运行的丰富的、由浏览器托管的应用程序。
-
它也可以与 HTML 共存。因此,Silverlight 可以增强现有的 Web 应用程序。
-
Silverlight 通过浏览器插件发挥其魔力。当您浏览包含 Silverlight 内容的网页时,此浏览器插件会运行、执行代码并在页面的特定指定区域中呈现该内容。
-
重要的部分是 Silverlight 插件提供了比支持普通网页的 HTML 和 JavaScript 的传统混合更丰富的环境。
-
您可以创建播放视频、具有硬件加速 3D 图形和使用矢量动画的 Silverlight 页面。
从开发人员的角度来看,Silverlight 最有趣的功能是它将 .NET Framework 编程模型带到您的 Web 应用程序的客户端。
-
Silverlight 旨在在网页内运行,因此它可以作为浏览器插件运行。它提供用于渲染位图、矢量图形、高清视频和动画的图形服务。
-
您可以使用 C# 或 Visual Basic .NET 编写,并在 Web 浏览器中运行的代码上使用 .NET Framework 类库功能。
-
Silverlight 用户界面本身使用与 Windows Presentation Foundation (WPF) 非常相似的模型,后者是完整桌面 .NET Framework 中的用户界面框架。
-
如果您了解 WPF,Silverlight 很容易上手。Silverlight 的下载量比 .NET 小得多。它大约是其大小的十分之一,因此只存在类库的一个子集,并且对 WPF 的模型产生了各种影响。
-
尽管规模缩小了,但经验丰富的 .NET 开发人员在 Silverlight 中会立即感到宾至如归。
平台和浏览器
Silverlight 支持的平台和浏览器是 –
视窗
-
Silverlight 支持 Windows,正如您对 Microsoft 产品所期望的那样。它至少需要 Windows XP Service Pack 2 或最新版本的 Windows。
-
不完全支持旧版本。例如,Silverlight 根本无法在 Windows ME 上运行,而 Windows 2000 的支持有限。
-
至于浏览器,Silverlight 支持微软自家的 Internet Explorer,当然也支持 Firefox 和 Google Chrome 版本 4。
-
从广义上讲,Silverlight 支持常见的 Web 浏览器插件 API。它适用于比官方支持的列表更广泛的浏览器。
苹果电脑
-
Silverlight 支持 Mac OS10,尽管 Silverlight 版本 2 或更高版本只能在基于 Intel 的 Mac 上运行。
-
在现代 Mac 上,Firefox 和 Safari 均受支持。
Linux
-
微软自己的 Silverlight 插件不能在 Linux 上运行,但是 Mono 开源项目有一个名为 Moonlight 的分支,它是一个可以在 Linux 上运行的 Silverlight 兼容插件。
-
Moonlight 在 Firefox 中运行,有趣的是,它一直能够在独立模式下运行。
-
Mono 项目最初决定构建 Moonlight 的原因之一是他们认为 Silverlight 将是构建在桌面上运行的用户界面小部件的有用技术。
Silverlight – 环境设置
Microsoft 为 Silverlight 应用程序开发提供了两个重要的工具。他们是 –
- 视觉工作室
- 表情混合
目前,这两种工具都可以创建 Silverlight 项目,但事实是开发人员更多地使用 Visual Studio,而设计人员仍然更频繁地使用 Blend。微软提供了免费版的visual studio,可以从https://www.visualstudio.com下载。在本教程中,我们将主要使用 Visual Studio。
安装
步骤 1 – 下载 Silverlight 后,运行安装程序。将显示以下对话框。
步骤 2 – 单击安装按钮,它将开始安装过程。
步骤 3 – 成功安装 Sivelight 后,您将看到以下对话框。
步骤 4 – 关闭此对话框并根据需要重新启动计算机。
第 5 步– 现在从“开始”菜单打开Visual Studio,这将打开如下所示的对话框。第一次凝视时,需要一些准备时间。
步骤 6 – 接下来,您将看到 Visual Studio 的主窗口。
第 7 步– 现在,要开始使用 Silverlight 应用程序,您还需要在您的机器上安装 Silverlight Developer 工具。从http://silverlight.dlservice.microsoft.com/download/8/E/7/8E7D9B4B-2088-4AED8356-20E65BE3EC91/40728.00/Silverlight_Developer_x64.exe下载并安装最新的 Silverlight Developer 工具
步骤 8 – 单击安装。安装需要一些时间。
步骤 9 – 安装完成后,您将看到以下消息。
第 10 步– 现在您已准备好构建您的第一个 Silverlight 应用程序。单击关闭。
Silverlight – 入门
在本章中,我们将查看 Silverlight 的一个工作示例。我们需要两件事 –
-
首先,我们需要一个网页。Silverlight 旨在用于富 Internet 应用程序,它旨在作为网页的一部分在 Web 浏览器内部运行。该页面需要包含一个合适的标签来加载 Silverlight 插件。它还可以包括检测是否安装 Silverlight 的逻辑,并且可以在不存在时提供一些后备用户界面。
-
我们需要的第二件事是 Silverlight 内容本身。本教程将重点介绍 Silverlight 的 .NET 编程模型。我们将创建一个已编译的 Silverlight 应用程序,其中包含 XAML、我们用来定义 Silverlight 用户界面的模型语言和用 C# 编写的 .NET 代码。
创建一个网页
开始使用 Silverlight 的最简单方法是创建一个带有 HTML 页面且没有服务器端代码的普通网站。让我们看一个非常简单的例子。
步骤 1 – 打开Visual Studio。单击文件菜单,指向新建,然后单击项目。
步骤 2 –将打开一个新项目对话框。在模板下,选择Visual C#,然后单击 Silverlight。在右侧窗格中,选择 Silverlight 应用程序。
输入项目名称和硬盘驱动器上的位置以保存项目,然后单击确定以创建项目。
Silverlight 项目本身将构建 Silverlight 内容,而该内容只是构成整个 Web 应用程序的众多资产中的一项。
单击“确定”。
步骤 3 – 检查托管 Silverlight 应用程序复选框。默认为 ASP.NET Web 应用程序项目。
第 4 步– MS-Visual Studio 创建了两个项目,Silverlight 项目和 ASP.NET Web 应用程序。现在,我们确实需要一个 ASP.NET Web 应用程序。您可以在解决方案资源管理器窗口中看到这一点,如下所示。
任何可以通过 HTTP 提供内容的东西都可以,但这是Visual Studio,它了解 ASP.NET Web 技术,所以这就是它给我们的。
为了证明 Silverlight 不依赖于任何特定的服务器端技术,让我们删除这个.aspx文件,只留下纯静态 HTML 文件。
步骤 5 – 右键单击 FirstExampleTestpage.aspx。从选项列表中,单击删除。
第 6 步– 将FirstExampleTestPage.html设置为起始页。
在MainPage.xaml中文件定义Silverlight内容的用户界面。您可以直接编写 XAML 代码,也可以使用Toolbox拖放不同的 UI 元素。
第 7 步– 下面给出了MainPage.xaml中的一个简单代码,其中在StackPanel中定义了一个Button和一个TextBlock。
<UserControl x:Class = "FirstExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel> <TextBlock x:Name = "TextMessage" Text = "Hello World!" Margin = "5"> </TextBlock> <Button x:Name = "ClickMe" Click = "ClickMe_Click" Content = "Click Me!" Margin = "5"> </Button> </StackPanel> </Grid> </UserControl>
步骤 8 – 此示例假设您已经创建了一个名为ClickMe_Click的事件处理方法。这是MainPage.xaml.cs文件中的样子。
using System.Windows; using System.Windows.Controls; namespace FirstExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void ClickMe_Click(object sender, RoutedEventArgs e) { TextMessage.Text = "Congratulations! you have created your first Silverlight Applicatoin"; } } }
步骤 9 – Silverlight 应用程序可以在任何已安装的浏览器上运行。
步骤 10 – 编译并执行上述代码后,您将看到以下网页。
步骤 11 – 现在,当您单击“单击我”按钮时,它将更新TextBlock 中的文本,如下所示。
我们建议您通过添加更多 UI 元素来执行上述示例。
Silverlight – XAML 概述
在使用 Silverlight 时,您首先会遇到的事情之一是 XAML。XAML 代表可扩展应用程序标记语言。它是一种基于 XML 的简单的声明性语言。
-
在 XAML 中,创建、初始化和设置具有层次关系的对象的属性非常容易。
-
它主要用于设计GUI。
-
它也可以用于其他目的,例如,在工作流基础中声明工作流。
基本语法
创建新的 Silverlight 项目时,默认情况下,您将在MainPage.xaml 中看到一些 XAML 代码,如下所示。
<UserControl x:Class = "FirstExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> </Grid> </UserControl>
可以看到上面给出的XAML文件提到了不同种类的信息;所有这些都在下表中进行了简要描述。
Information | 描述 |
---|---|
<UserControl | 提供用于定义新控件的基类,该控件封装现有控件并提供其自己的逻辑。 |
x:Class = “FirstExample.MainPage” | 它是一个分部类声明,它将标记连接到后面定义的分部类代码。 |
xmlns = “http://schemas.microsoft.com /winfx/2006/xaml/presentation” | 映射 Silverlight 客户端/框架的默认 XAML 命名空间。 |
xmlns:x = “http://schemas.microsoft.c om/winfx/2006/xaml” | XAML 语言的 XAML 命名空间,将其映射到 x: 前缀。 |
xmlns:d = “http://schemas.microsoft.com /expression/blend/2008” | XAML 命名空间用于设计器支持,特别是 Microsoft Visual Studio 和 Microsoft Expression Blend 的 XAML 设计图面中的设计器支持。 |
xmlns:mc = “http://schemas.openxmlforma ts.org/markup-compatibility/2006” | 指示并支持用于读取 XAML 的标记兼容模式。 |
> | 根对象元素的结尾。 |
<Grid></Grid> | 这些是空网格对象的开始和结束标记。 |
</UserControl> | 关闭对象元素。 |
XAML 的语法规则与 XML 的语法规则几乎相似。如果您查看 XAML 文档,您会注意到它实际上是一个有效的 XML 文件。反之则不然,因为在 XML 中,属性的值必须是字符串,而在 XAML 中,它可以是不同的对象,称为属性元素语法。
-
Object 元素的语法以左尖括号 (<) 开头,后跟对象的名称,例如 Button。
-
定义了该对象元素的属性和属性。
-
Object 元素必须以正斜线 (/) 结束,后跟右尖括号 (>)。
下面显示了一个没有子元素的简单对象的示例。
<Button/>
具有某些属性的对象元素的示例 –
<Button Content = "Click Me" Height = "30" Width = "60"/>
定义属性的替代语法示例(属性元素语法) –
<Button> <Button.Content>Click Me</Button.Content> <Button.Height>30</Button.Height> <Button.Width>60</Button.Width> </Button>
具有子元素的对象示例:StackPanel 包含 Textblock 作为子元素。
<StackPanel Orientation = "Horizontal"> <TextBlock Text = "Hello"/> </StackPanel/>
为什么在 Silverlight 中使用 XAML
XAML 最初并不是为 Silverlight 发明的。它来自 WPF,即 Windows Presentation Foundation。Silverlight 通常被描述为 WPF 的一个子集。这并非严格正确,因为 Silverlight 可以做一些 WPF 不能做的事情。即使在功能重叠的地方,两者在细节上也略有不同。
-
更准确地说,WPF 和 Silverlight 在许多方面非常相似。尽管存在差异,但查看 Silverlight 从 WPF 借用的 XAML 功能仍然是有益的。例如,Silverlight 为位图和可缩放形状提供图形基元。
-
它还提供用于渲染视频和音频的元素。
-
它具有简单的格式化文本支持,您可以为任何元素设置动画。如果您了解 WPF,那么您就会熟悉此功能集。
-
重要的一点是,您不能采用 WPF XAML 并在 Silverlight 中使用它。
-
尽管有相似之处,但您也会发现许多细微的差异。
XAML 和代码隐藏
XAML 定义了用户界面的外观和结构。但是,如果您希望您的应用程序在用户与其交互时做任何有用的事情,您将需要一些代码。
-
每个 XAML 文件通常都与一个源代码文件相关联,我们将其称为背后的代码。各种 Microsoft 框架都使用这个术语。
-
后面的代码通常需要使用 XAML 中定义的元素,以检索有关用户输入的信息,或向用户显示信息。
-
在下面给出的 XAML 代码中,定义了TextBlock和Button。默认情况下,当应用程序运行时,它会显示一个文本“ Hello World!”在网页上和一个按钮。
<UserControl x:Class = "FirstExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel> <TextBlock x:Name = "TextMessage" Text = "Hello World!" Margin = "5"> </TextBlock> <Button x:Name = "ClickMe" Click = "ClickMe_Click" Content = "Click Me!" Margin = "5"> </Button> </StackPanel> </Grid> </UserControl>
-
后面的代码可以访问任何以x:Name指令命名的元素。
-
命名元素通过后面代码中的字段变得可用,允许代码以通常的方式访问这些对象及其成员。
-
在X:前缀表示该名称不是一个正常的财产。
-
x:Name是 XAML 编译器的一个特殊信号,我们希望在后面的代码中访问此对象。
下面给出了更新TextBlock文本的按钮单击事件实现。
using System.Windows; using System.Windows.Controls; namespace FirstExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void ClickMe_Click(object sender, RoutedEventArgs e) { TextMessage.Text = "Congratulations! you have created your first Silverlight Applicatoin"; } } }
-
XAML 不是设计 UI 元素的唯一方法。您可以在 XAML 中声明对象或在代码中声明/编写。
-
XAML 是可选的,但尽管如此,它仍然是Silverlight设计的核心。
-
XAML 编码的目标是使可视化设计人员能够直接创建用户界面元素。因此,Silverlight旨在通过标记来控制用户界面的所有视觉方面。
Silverlight – 项目类型
如果在 Visual Studio 中创建新项目,您将在对话框的右窗格中看到四种类型的项目。他们是 –
- Silverlight 应用程序
- Silverlight 类库
- 类库(便携式)
- Silverlight 导航应用程序
-
前两个Silverlight Application和Silverlight Class Library非常简单。这些类似于经典 Windows 应用程序世界中 DLL 中的可执行文件。由于 Silverlight 应用程序的部署方式,两者都构建 DLL。
-
从概念上讲,Silverlight 应用程序项目构建了一个可以运行的程序,而类库项目构建了一个旨在合并到其他应用程序中的库。
-
如果您计划构建多个应用程序,并希望重用公共代码,则可以构建一个类库。如果您打算出售其他人将在他们的应用程序中使用的控件,那么再次构建一个库。
-
其他项目类型不太明显,因此我们将在本章后面详细介绍这些类型。
Silverlight Web 应用程序
Silverlight 应用程序是从 Web 下载的,因此您通常会有一个与 Silverlight 项目相关联的 Web 项目。Visual Studio 有几个功能,旨在管理这些项目之间的关系。
让我们再看一个 Silverlight Application 项目的简单例子。
步骤 1 – 打开Visual Studio。单击文件菜单,指向新建,然后单击项目。
步骤 2 –将打开一个新项目对话框。在模板下,选择Visual C#,然后单击 Silverlight。在右侧窗格中,选择 Silverlight 应用程序。
输入项目名称和硬盘驱动器上的位置以保存项目。
Silverlight 项目本身将构建 Silverlight 内容,而该内容只是构成整个 Web 应用程序的众多资产中的一项。
单击“确定”。
步骤 3 – 检查托管 Silverlight 应用程序复选框。默认为 ASP.NET Web 应用程序项目。
第 4 步– MS-Visual Studio 创建了两个项目,Silverlight 项目和 ASP.NET Web 应用程序。现在,我们需要一个 ASP.NET Web 应用程序。您可以在解决方案资源管理器窗口中看到这一点,如下所示。
任何可以通过 HTTP 提供内容的东西都可以,但这是Visual Studio,它了解 ASP.NET Web 技术,所以这就是它给我们的。
为了证明 Silverlight 不依赖于任何特定的服务器端技术,让我们删除这个.aspx文件,只留下纯静态 HTML 文件。
步骤 5 – 右键单击 FirstExampleTestpage.aspx。从选项列表中,单击删除。
第 6 步– 将FirstExampleTestPage.html设置为起始页。
在MainPage.xaml中文件定义Silverlight内容的用户界面。您可以直接编写 XAML 代码,也可以使用Toolbox拖放不同的 UI 元素。
第 7 步– 下面给出了MainPage.xaml中的一个简单代码,其中在StackPanel中定义了一个Button和一个TextBlock。
<UserControl x:Class = "FirstExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel> <TextBlock x:Name = "TextMessage" Text = "Hello World!" Margin = "5"> </TextBlock> <Button x:Name = "ClickMe" Click = "ClickMe_Click" Content = "Click Me!" Margin = "5"> </Button> </StackPanel> </Grid> </UserControl>
步骤 8 – 此示例假设您已经创建了一个名为ClickMe_Click的事件处理方法。这是MainPage.xaml.cs文件中的样子。
using System.Windows; using System.Windows.Controls; namespace FirstExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void ClickMe_Click(object sender, RoutedEventArgs e) { TextMessage.Text = "Congratulations! you have created your first Silverlight Applicatoin"; } } }
步骤 9 – Silverlight 应用程序可以在任何已安装的浏览器上运行。
步骤 10 – 编译并执行上述代码后,您将看到以下网页。
Silverlight 导航应用程序
Silverlight 导航应用程序模板构建一个类似于普通 Silverlight 应用程序的项目。这两种项目类型没有根本区别。导航模板仅包含一些您可以轻松添加的附加代码。顾名思义,它支持 Silverlight 应用程序中的类似 Web 的导航。
让我们创建一个导航应用程序。
步骤 1 –从“新建项目”对话框的右侧窗格中选择Silverlight 导航应用程序。
第 2 步– 按照您对 Silverlight Web 应用程序所做的设置进行操作。
步骤 3 – 单击确定按钮。将打开一个窗口,如下所示。
这些通常有一个关联的 Web 项目,因此我们将拥有其中之一。如前所述,它创建了两个项目,但正如您所看到的,默认用户界面看起来不那么空白。
第 4 步– 它提供了一个应用程序 Chrome,包括一个导航栏。该解决方案包含一些额外的文件。此样式文件定义导航栏的外观。在这个Views文件夹中,我们看到了几个页面,还有一个显示错误的窗口。
如您所见,当您运行该应用程序时,它会显示一个包含一些占位符内容的主页。
步骤 5 – 当您单击关于按钮时,它将导航到关于页面。
重要的是,您可以使用浏览器的“后退”和“前进”按钮来回溯这些步骤。
通常,当您执行此操作时,Web 浏览器会从一个网页转到另一个网页,但在这里不会。Silverlight 应用程序实际上并没有卸载;它保持运行,只是显示不同的内容。
因此,从浏览器的角度来看,它实际上都在一个网页上。Silverlight 对导航按钮使用了一些技巧,以确保网页在我们导航时不会卸载。
Silverlight – 固定布局
控件的布局对于应用程序的可用性非常重要和关键。它用于在您的应用程序中排列一组 GUI 元素。选择布局面板时需要考虑一些重要的事情。他们是 –
- 子元素的位置。
- 子元素的大小。
- 重叠的子元素相互叠加。
如果应用程序已在不同的屏幕分辨率上使用,则控件的固定像素排列不起作用。XAML 提供了一组丰富的内置布局面板,以适当的方式排列 GUI 元素。
我们将从查看简单的固定布局开始。然后我们将查看Silverlight 设计支持的动态布局方案。我们将看到渗透到所有用户界面元素的与布局相关的属性和概念。
固定布局
Canvas元素提供了最简单的布局。的画布面板是基本布局面板,其中,子元素可以明确地使用是相对于帆布的任一侧,诸如左,右,顶和底的坐标定位。
通常,画布用于 2D 图形元素(例如椭圆、矩形等)。它不用于 UI 元素,因为在调整 XAML 应用程序的大小、本地化或缩放时指定绝对坐标会带来麻烦。
下面给出了Canvas类的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Background 获取或设置填充面板内容区域的 Brush。(继承自面板) |
2 |
Children 获取此 Panel 的子元素的 UIElementCollection。(继承自面板。) |
3 |
Height 获取或设置元素的建议高度。(继承自 FrameworkElement。) |
4 |
ItemHeight 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的高度。 |
5 |
ItemWidth 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的宽度。 |
6 |
LogicalChildren 获取可以迭代此 Panel 元素的逻辑子元素的枚举数。(继承自面板。) |
7 |
LogicalOrientation 面板的方向,如果面板仅支持单一维度的布局。(继承自面板。) |
8 |
LeftProperty 标识 Canvas.Left XAML 附加属性。 |
9 |
Margin 获取或设置元素的外边距。(继承自 FrameworkElement。) |
10 |
Name 获取或设置元素的标识名称。该名称提供了一个引用,以便代码隐藏(例如事件处理程序代码)可以在 XAML 处理器在处理期间构造标记元素后引用该标记元素。(继承自 FrameworkElement。) |
11 |
Orientation 获取或设置一个值,该值指定排列子内容的维度。 |
12 |
Parent 获取此元素的逻辑父元素。(继承自 FrameworkElement。) |
13 |
Resources 获取或设置本地定义的资源字典。(继承自 FrameworkElement。) |
14 |
Style 获取或设置此元素在呈现时使用的样式。(继承自 FrameworkElement。) |
15 |
TopProperty 标识 Canvas.Top XAML 附加属性。 |
16 |
Width 获取或设置元素的宽度。(继承自 FrameworkElement。) |
17 |
ZIndexProperty 标识 Canvas.ZIndex XAML 附加属性。 |
下面给出Canvas的常用方法。
Sr. No. | 方法和说明 |
---|---|
1 |
GetLeft 获取目标元素的 Canvas.Left XAML 附加属性的值。 |
2 |
GetTop 获取目标元素的 Canvas.Top XAML 附加属性的值。 |
3 |
GetZIndex 获取目标元素的 Canvas.ZIndex XAML 附加属性的值。 |
4 |
SetLeft 设置目标元素的 Canvas.Left XAML 附加属性的值。 |
5 |
SetTop 设置目标元素的 Canvas.Top XAML 附加属性的值。 |
6 |
SetZIndex 设置目标元素的 Canvas.ZIndex XAML 附加属性的值。 |
以下示例显示了如何将子元素添加到Canvas 中。下面是 XAML 实现,其中在具有不同偏移属性的 Canvas 内创建 Ellipse。
<UserControl x:Class = "FirstExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Canvas Width = "380" Height = "280" > <Ellipse Canvas.Left = "30" Canvas.Top = "30" Fill = "Gray" Width = "200" Height = "120" /> </Canvas> </Grid> </UserControl>
当上面的代码编译执行后,你会看到下面的输出。
Silverlight – 动态布局
该画布是所有的Silverlight的布局面板的最无趣。其他面板启用Dynamic Layouts,这意味着布局可以随着显示项目数量的变化、显示信息的大小的变化,或者由于用户调整浏览器大小而导致应用程序可用空间量发生变化时进行调整。
Silverlight 提供了两个具有动态布局策略的面板。
-
StackPanel – 将元素排列在垂直或水平堆栈中。
-
Grid – 提供灵活的类似网格或类似表格的布局系统。
堆栈面板
Stack panel 是一个简单而有用的 XAML 布局面板。在Stack Panel 中,子元素可以根据它们的方向属性水平或垂直排列在一行中。每当需要创建任何类型的列表时,通常会使用它。ItemsControls 使用堆栈面板。Menu、ListBox和ComboBox是它们默认的内部布局面板。
下面给出了StackPanel的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Background 获取或设置填充面板内容区域的 Brush。(继承自面板) |
2 |
Children 获取此 Panel 的子元素的 UIElementCollection。(继承自面板。) |
3 |
Height 获取或设置元素的建议高度。(继承自 FrameworkElement。) |
4 |
ItemHeight 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的高度。 |
5 |
ItemWidth 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的宽度。 |
6 |
LogicalChildren 获取可以迭代此 Panel 元素的逻辑子元素的枚举数。(继承自面板。) |
7 |
LogicalOrientation 面板的方向,如果面板仅支持单一维度的布局。(继承自面板。) |
8 |
Margin 获取或设置元素的外边距。(继承自 FrameworkElement。) |
9 |
Name 获取或设置元素的标识名称。该名称提供了一个引用,以便代码隐藏(例如事件处理程序代码)可以在 XAML 处理器在处理期间构造标记元素后引用该标记元素。(继承自 FrameworkElement。) |
10 |
Orientation 获取或设置一个值,该值指定排列子内容的维度。 |
11 |
Parent 获取此元素的逻辑父元素。(继承自 FrameworkElement。) |
12 |
Resources 获取或设置本地定义的资源字典。(继承自 FrameworkElement。) |
13 |
Style 获取或设置此元素在呈现时使用的样式。(继承自 FrameworkElement。) |
14 |
Width 获取或设置元素的宽度。(继承自 FrameworkElement。) |
以下示例显示如何将子元素添加到StackPanel 中。下面给出的是 XAML 实现,其中在具有某些属性的 StackPanel 内创建按钮。
<UserControl x:Class = "DynamicLayout.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel> <Button x:Name = "button" Content = "Button" Margin = "10" /> <Button x:Name = "button1" Content = "Button" Margin = "10"/> <Button x:Name = "button2" Content = "Button" Margin = "10"/> <Button x:Name = "button3" Content = "Button" Margin = "10"/> </StackPanel> </Grid> </UserControl>
当上面的代码编译执行后,你会看到下面的输出。
StackPanel 尝试为每个元素安排在堆叠方向上所需的尽可能多的空间。
现在,如果您调整浏览器的大小,您将看到按钮的宽度也发生了变化。
网格
网格面板提供了一个灵活的区域,由行和列组成。在Grid 中,子元素可以以表格形式排列。可以使用Grid.Row和Grid.Column属性将元素添加到任何特定的行和列。默认情况下,网格面板创建为一行和一列。多行和多列由RowDefinitions和ColumnDefinitions属性创建。行高和列宽可以通过以下三种方式定义 –
-
固定值– 分配固定大小的逻辑单元(1/96 英寸)。
-
Auto – 它将占用该特定行/列中的控件所需的空间。
-
Star (*) –填充自动和固定大小时将占用剩余空间。
下面给出了Grid类的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Background 获取或设置填充面板内容区域的 Brush。(继承自面板) |
2 |
Children 获取此 Panel 的子元素的 UIElementCollection。(继承自面板。) |
3 |
ColumnDefinitions 获取在此 Grid 实例上定义的 ColumnDefinition 对象的列表。 |
4 |
Height 获取或设置元素的建议高度。(继承自 FrameworkElement。) |
5 |
ItemHeight 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的高度。 |
6 |
ItemWidth 获取或设置一个值,该值指定包含在 WrapPanel 中的所有项目的宽度。 |
7 |
Margin 获取或设置元素的外边距。(继承自 FrameworkElement。) |
8 |
Name 获取或设置元素的标识名称。该名称提供了一个引用,以便代码隐藏(例如事件处理程序代码)可以在 XAML 处理器在处理期间构造标记元素后引用该标记元素。(继承自 FrameworkElement。) |
9 |
Orientation 获取或设置一个值,该值指定排列子内容的维度。 |
10 |
Parent 获取此元素的逻辑父元素。(继承自 FrameworkElement。) |
11 |
Resources 获取或设置本地定义的资源字典。(继承自 FrameworkElement。) |
12 |
RowDefinitions 获取在此 Grid 实例上定义的 RowDefinition 对象列表。 |
13 |
Style 获取或设置此元素在呈现时使用的样式。(继承自 FrameworkElement。) |
14 |
Width 获取或设置元素的宽度。(继承自 FrameworkElement。) |
下面给出了Grid类的常用方法。
Sr. No. | 方法和说明 |
---|---|
1 |
GetColumn 从指定的 FrameworkElement 获取 Grid.Column XAML 附加属性的值。 |
2 |
GetColumnSpan 从指定的 FrameworkElement 获取 Grid.ColumnSpan XAML 附加属性的值。 |
3 |
GetRow 从指定的 FrameworkElement 获取 Grid.Row XAML 附加属性的值。 |
4 |
SetColumn 在指定的 FrameworkElement 上设置 Grid.Column XAML 附加属性的值。 |
5 |
SetRow 在指定的 FrameworkElement 上设置 Grid.Row XAML 附加属性的值。 |
6 |
SetRowSpan 在指定的 FrameworkElement 上设置 Grid.RowSpan XAML 附加属性的值。 |
以下示例显示如何将子元素添加到 Grid 以表格形式指定它。下面给出了 XAML 实现,其中添加了一些 UI 元素。
<UserControl x:Class = "DynamicLayout.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Grid.ColumnDefinitions> <ColumnDefinition Width = "130" /> <ColumnDefinition Width = "1*" /> <ColumnDefinition Width = "2*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition Height = "50" /> </Grid.RowDefinitions> <TextBlock Grid.Column = "0" Grid.Row = "0" Text = "Content that no longer fits, not even close here" TextWrapping = "Wrap" /> <Button Grid.Column = "1" Grid.Row = "0" Content = "OK" /> <Ellipse Grid.Column = "1" Grid.Row = "1" Fill = "Aqua" /> <Rectangle Grid.Column = "2" Grid.Row = "1" Fill = "Orchid" RadiusX = "20" RadiusY = "20" /> </Grid> </UserControl>
第一列设置为固定大小。此列中的任何元素都将具有该宽度。Grid.Column和Grid.Row属性指定这些项目所在的行和列,这些是基于 0 的属性。
第二列或第三列的宽度为1*和2*。这意味着在任何固定和自动宽度的列占用了它们的空间后,它们会共享剩余的空间。这里1和2的意义在于2*列获得的空间是1*列的两倍。
执行上述代码后,您将看到以下输出。
当您调整应用程序的大小时,这两列的内容会调整大小以匹配。顺便说一句,星形大小的行或列的绝对值无关紧要;只有比率才是重要的。
受约束与不受约束的布局
Silverlight 中的布局始终以两种模式之一进行,即受约束或不受约束。约束布局是一种,其中容器强加宽度或高度。例如,通常使用 CSS 的 Web 浏览器始终决定 Silverlight 插件的整体尺寸。
一些重要的功能是 –
-
顶层元素布局在水平和垂直方向上都受到约束。无论它产生什么布局,它最终都必须以浏览器强加的大小结束。
-
一些元素以无约束布局结束,这意味着元素可以自由选择自己的大小。例如,垂直StackPanel内的元素在垂直方向上不受约束。
-
StackPanel 将为它们提供所需的高度。事实上,即使没有足够的空间,它也会这样做。它会告诉元素他们有他们需要的高度,然后裁剪任何不合适的东西。
-
大多数 Silverlight 用户界面都包含这两种布局样式的混合。无论其父级是否施加约束,StackPanel将始终在堆叠方向上执行不受约束的布局。当高度或宽度设置为Auto时,对于 Grid 行或列也是如此。
假设您有一个元素,它位于一个容器内,该容器具有固定的水平宽度。默认情况下,您的元素将被拉伸以填充空间。如果将对齐方式设置为左对齐、右对齐或居中对齐,则会移除约束。
元素将只采用它需要的宽度。当然,你可以引入一个固定宽度或高度的约束。
-
无约束布局有时称为“内容大小”,因为无约束元素的大小通常由其内容决定。
-
按内容大小是 Silverlight 布局中的一个重要思想。它使布局能够适应正在显示的任何信息。
Sr. No. | 控制和描述 |
---|---|
1 | GridSplitter
约束可以来自包含浏览器或设计中的固定尺寸。但是,让用户施加约束有时很有用。 |
2 | ScrollViewer
一些用户界面最终需要显示比可用空间更多的信息。对此的一种常见解决方案是提供可滚动区域。Silverlight 使用 ScrollViewer 使这变得非常容易。 |
3 | Border
在布局用户界面时要记住的另一个有用的元素是边框。 |
全屏模式
Silverlight 插件能够接管整个屏幕。您可以在辅助类上设置一个属性以进入全屏模式。但是,出于安全目的,存在一些限制。为了防止网站能够随意接管屏幕,并做一些邪恶的事情,比如伪造一个要求用户密码的提示。
要进入全屏模式,您需要从应用程序对象中获取 Host.Content 属性,并将其 IsFullScreen 属性设置为 true。
让我们看一个简单的例子,它切换属性,所以它会在全屏和正常之间来回切换。
<UserControl x:Class = "FullScreenExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Border BorderBrush = "Gray" BorderThickness = "4" CornerRadius = "30" Padding = "20"> <Border.Background> <LinearGradientBrush StartPoint = "0,0" EndPoint = "0,1"> <GradientStop Offset = "0" Color = "Wheat" /> <GradientStop Offset = "1" Color = "BurlyWood" /> </LinearGradientBrush> </Border.Background> <Grid x:Name = "LayoutRoot"> <Button x:Name = "fullScreenButton" HorizontalAlignment = "Center" VerticalAlignment = "Center" FontSize = "30" Width = "300" Height = "100" Content = "Go Full Screen" Click = "Button_Click" /> </Grid> </Border> </UserControl>
这是 C# 中的代码,用于启动从全屏返回正常屏幕。您可以通过处理Host.Content对象FullScreenChanged事件来确定何时发生这种情况。
using System; using System.Windows; using System.Windows.Controls; namespace FullScreenExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); App.Current.Host.Content.FullScreenChanged += Content_FullScreenChanged; } void Content_FullScreenChanged(object sender, EventArgs e) { if (Application.Current.Host.Content.IsFullScreen) { fullScreenButton.Content = "Return to Normal"; } else { fullScreenButton.Content = "Go Full Screen"; } } private void Button_Click(object sender, RoutedEventArgs e) { var content = Application.Current.Host.Content; content.IsFullScreen = !content.IsFullScreen; } } }
当上面的代码编译执行后,你会看到下面的输出。
当用户单击Go Full Screen按钮时,它将切换到全屏模式。
请注意,按钮的文本已更改。它现在说Return to Normal。如果您再次单击它或按 Escape 键,它将退出全屏模式。
Silverlight – CSS
由于 Silverlight 内容始终在网页内运行,因此对象标记受常规 CSS 布局规则的约束。插件无法将首选大小推送回浏览器,因此无论 Silverlight 内容的大小如何,其大小和位置都将完全由包含的网页决定。
-
默认的 Silverlight 项目模板将 CSS 放在网页中,为整个浏览器窗口提供对象标记。
-
默认 XAML 似乎具有固定大小,但如果仔细观察,您将看到模板设置了设计宽度和设计高度属性。
-
它们告诉 Visual Studio 或 Blend,用户界面在设计器中应该有多大,但它们允许它在运行时调整大小。
在解决方案资源管理器中,您将看到{project name}TestPage.html文件,这是您在 Visual Studio 中创建新 Silverlight 项目时获得的默认 HTML,如下所示。
此处顶部的 CSS 将 HTML 和正文样式设置为 100%,这可能看起来有点奇怪。
这是完整的 html 文件,其中包含不同的设置。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" > <head> <title>FirstExample</title> <style type = "text/css"> html, body { height: 100%; overflow: auto; } body { padding: 0; margin: 0; } #silverlightControlHost { height: 100%; text-align:center; } </style> <script type = "text/javascript" src = "Silverlight.js"></script> <script type = "text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; if (errorType == "ImageError" || errorType == "MediaError") { return; } var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n" ; errMsg += "Code: "+ iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; } throw new Error(errMsg); } </script> </head> <body> <form id = "form1" runat = "server" style = "height:100%"> <div id = "silverlightControlHost"> <object data = "data:application/x-silverlight-2," type = "application/xsilverlight-2" width = "100%" height = "100%"> <param name = "source" value = "ClientBin/FirstExample.xap"/> <param name = "onError" value = "onSilverlightError" /> <param name = "background" value = "white" /> <param name = "minRuntimeVersion" value = "5.0.61118.0" /> <param name = "autoUpgrade" value = "true" /> <a href = "http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style = "textdecoration:none"> <img src = "http://go.microsoft.com/fwlink/?LinkId=161376" alt = "Get Microsoft Silverlight" style = "border-style:none"/> </a> </object> <iframe id = "_sl_historyFrame" style = "visibility:hidden;height:0px; width:0px;border:0px"></iframe> </div> </form> </body> </html>
查看silverlightControlHost,我们需要确保它具有固定的高度(例如 300 像素)和 400 像素的宽度,这与 XAML 中的默认设计宽度和高度相匹配。您还可以根据您的应用程序要求更改这些设置。
重叠内容
默认情况下,Silverlight 和 HTML 内容不能共享屏幕上的相同空间。如果您从两者制作内容,使它们占据相同的空间,则只有 Silverlight 内容可见。
这是因为,默认情况下,Silverlight 会要求浏览器提供自己的私有窗口,将所有内容渲染到该窗口中。它是浏览器内部的子窗口,因此看起来像网页的一部分,但它可以防止内容重叠。
造成这种情况的主要原因是性能。通过在屏幕上获得自己的私人区域,Silverlight 不必与 Web 浏览器协调其渲染。
但是,有时重叠的内容很有用。需要付出性能代价。您可能会发现,当 Silverlight 和 HTML 在屏幕上共享空间时,动画的运行并不流畅,但额外的布局灵活性可能值得付出代价。要使用重叠内容,您需要启用无窗口模式。
-
在无窗口模式下,Silverlight 插件呈现给与浏览器相同的目标窗口处理程序,允许内容混合。
-
当内容重叠时,Zed 索引或 Z 索引很重要。就 HTML 而言,Silverlight 内容是单个 HTML 元素,因此它恰好出现在 HTML Z 顺序中的一个位置。
-
这对鼠标处理有影响。如果 Silverlight 插件位于 HMTL Z 顺序的顶部,则其边界框内任何位置的任何鼠标活动都将传递给插件。
-
即使插件的某些区域是透明的,您可以看到后面的 HTML,您也无法单击它。
-
但是,如果您将带有一些 HTML 内容的 Z 索引安排在顶部,即使它与 Silverlight 内容重叠,它也将继续是交互式的。
例子
看看下面给出的简单示例,其中我们有一个带有容器的布局,其中三个 div 都被安排在这个包含 div 的内部重叠。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" > <head> <title>HtmlOverlap</title> <style type = "text/css"> #container { position: relative; height: 300px; font-size: small; text-align:justify; } #silverlightControlHost { position: absolute; width: 400px; height: 300px; } #underSilverlight { position: absolute; left: 4px; width: 196px; } #overSilverlight { position: relative; left: 204px; width: 196px; } </style> <script type = "text/javascript" src = "Silverlight.js"></script> <script type = "text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; if (errorType == "ImageError" || errorType == "MediaError") { return; } var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n" ; errMsg += "Code: "+ iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; } throw new Error(errMsg); } </script> </head> <body> <form id = "form1" runat = "server" style = "height:100%"> <div id = 'container'> <div id = 'underSilverlight'> This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. This is below. </div> <div id = "silverlightControlHost"> <object data = "data:application/x-silverlight-2," type = "application/xsilverlight-2" width = "100%" height = "100%"> <param name = "source" value = "ClientBin/HtmlOverlap.xap"/> <param name = "onError" value = "onSilverlightError" /> <param name = "background" value = "transparent" /> <param name = "windowless" value = "true" /> <param name = "minRuntimeVersion" value = "4.0.50401.0" /> <param name = "autoUpgrade" value = "true" /> <a href = "http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0" style = "text-decoration:none"> <img src = "http://go.microsoft.com/fwlink/?LinkId=161376" alt = "Get Microsoft Silverlight" style = "border-style:none"/> </a> </object> <iframe id = "_sl_historyFrame" style = "visibility:hidden; height:0px; width:0px; border:0px"> </iframe> </div> <div id = 'overSilverlight'> This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. This is on top. </div> </div> </form> </body> </html>
-
这个 div 向左移动,它将在 Z 顺序的后面,因为它排在最前面。
-
然后在中间,我们有将填充整个宽度的 Silverlight 内容。
-
然后在此之上,右侧有一个 div 包含文本- This is on top。
下面给出的是 XAML 文件,其中添加了一个带有一些属性的矩形。
<UserControl x:Class = "HtmlOverlap.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot"> <Rectangle Margin = "0,120" Fill = "Aquamarine" /> </Grid> </UserControl>
当你运行这个应用程序时,你会看到两列,一列在左边,一列在右边。Silverlight 插件与这两个插件位于同一区域,并且按照 Z 顺序,Silverlight 内容位于这两者的中间。
您可以看到此处的半透明绿色填充对左侧的文本进行了轻微着色,因为它位于该文本的顶部,但并未对右侧的文本进行着色,因为它位于该文本的后面。
您可以选择右侧的文本。如果您尝试使用左侧的此文本,则没有任何反应,这是因为就浏览器而言,此处的整个空间都被 Silverlight 控件占用。由于它在 Z 顺序中的文本上方,因此处理输入的 Silverlight 控件。
Silverlight – 控件
所有控件都具有某种交互行为,例如,当您将鼠标移到按钮上时按钮亮起并按下它时按下按钮的方式,列表框的滚动和选择行为。在所有情况下,控件都超越了简单的可见性。它可能比看起来更复杂。这些控件是父控件和代码的组合。Silverlight 允许开发人员轻松构建和创建视觉丰富的基于 UI 的应用程序。这些控件将 Silverlight 与其他元素区分开来。
一些重要的功能是 –
-
其他 UI 框架中的经典 UI 元素或控件也在 Silverlight 应用程序中得到了增强。
-
几乎所有标准 Silverlight 控件都可以在工具箱中找到,它是System.Windows.Controls的一部分。
-
这些控件也可以用 XAML 标记语言创建。
Silverlight 控件的完整继承层次结构如下 –
Silverlight – 按钮
该按钮类表示按钮控制的最基本类型。Silverlight 识别三种类型的按钮控件:熟悉的Button、CheckBox和RadioButton。所有这些控件都是从ButtonBase派生的内容控件。Button 类的分层继承如下 –
下面给出了按钮最常用的属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Background 获取或设置提供控件背景的画笔。(继承自 Control) |
2 |
BorderBrush 获取或设置描述控件边框填充的画笔。(继承自 Control) |
3 |
BorderThickness 获取或设置控件的边框粗细。(继承自 Control) |
4 |
Content 获取或设置 ContentControl 的内容。(继承自 ContentControl) |
5 |
ClickMode 获取或设置一个值,该值在设备行为方面指示 Click 事件发生的时间。(继承自 ButtonBase) |
6 |
ContentTemplate 获取或设置用于显示 ContentControl 内容的数据模板。(继承自 ContentControl) |
7 |
FontFamily 获取或设置用于在控件中显示文本的字体。(继承自 Control) |
8 |
FontSize 获取或设置此控件中文本的大小。(继承自 Control) |
9 |
FontStyle 获取或设置呈现文本的样式。(继承自 Control) |
10 |
FontWeight 获取或设置指定字体的粗细。(继承自 Control) |
11 |
Foreground 获取或设置描述前景色的画笔。(继承自 Control) |
12 |
Height 获取或设置 FrameworkElement 的建议高度。(继承自 FrameworkElement) |
13 |
HorizontalAlignment 获取或设置在布局父级(如面板或项目控件)中组合时应用于 FrameworkElement 的水平对齐特征。(继承自 FrameworkElement) |
14 |
IsEnabled 获取或设置一个值,该值指示用户是否可以与控件交互。(继承自 Control) |
15 |
IsPressed 获取一个值,该值指示 ButtonBase 当前是否处于按下状态。(继承自 ButtonBase) |
16 |
Margin 获取或设置 FrameworkElement 的外边距。(继承自 FrameworkElement) |
17 |
Name 获取或设置对象的标识名称。当 XAML 处理器从 XAML 标记创建对象树时,运行时代码可以通过此名称引用 XAML 声明的对象。(继承自 FrameworkElement) |
18 |
Opacity 获取或设置对象的不透明度程度。(继承自 UIElement) |
19 |
Resources 获取本地定义的资源字典。在 XAML 中,您可以通过 XAML 隐式集合语法将资源项建立为 frameworkElement.Resources 属性元素的子对象元素。(继承自 FrameworkElement) |
20 |
Style 获取或设置在布局和呈现期间应用于此对象的实例 Style。(继承自 FrameworkElement) |
21 |
Template 获取或设置控件模板。控件模板在 UI 中定义控件的视觉外观,并在 XAML 标记中定义。(继承自 Control) |
22 |
VerticalAlignment 获取或设置在父对象(如面板或项目控件)中组合时应用于 FrameworkElement 的垂直对齐特征。(继承自 FrameworkElement) |
23 |
Visibility 获取或设置 UIElement 的可见性。不可见的 UIElement 不会呈现,并且不会将其所需的大小传达给布局。(继承自 UIElement) |
24 |
Width 获取或设置 FrameworkElement 的宽度。(继承自 FrameworkElement) |
下面给出Button常用的方法。
Sr. No. | 方法和说明 |
---|---|
1 |
ClearValue 清除依赖属性的本地值。(继承自 DependencyObject) |
2 |
FindName 检索具有指定标识符名称的对象。(继承自 FrameworkElement) |
3 |
OnApplyTemplate 每当应用程序代码或内部进程(例如重建布局过程)调用 ApplyTemplate 时调用。简单来说,这意味着该方法会在 UI 元素显示在您的应用中之前被调用。覆盖此方法以影响类的默认后模板逻辑。(继承自 FrameworkElement) |
4 |
OnContentChanged 当 Content 属性的值更改时调用。(继承自 ContentControl) |
5 |
OnDragEnter 在 DragEnter 事件发生之前调用。(继承自 Control) |
6 |
OnDragLeave 在 DragLeave 事件发生之前调用。(继承自 Control) |
7 |
OnDragOver 在 DragOver 事件发生之前调用。(继承自 Control) |
8 |
OnDrop 在 Drop 事件发生之前调用。(继承自 Control) |
9 |
OnGotFocus 在 GotFocus 事件发生之前调用。(继承自 Control) |
10 |
OnKeyDown 在 KeyDown 事件发生之前调用。(继承自 Control) |
11 |
OnKeyUp 在 KeyUp 事件发生之前调用。(继承自 Control) |
12 |
OnLostFocus 在 LostFocus 事件发生之前调用。(继承自 Control) |
13 |
SetBinding 使用提供的绑定对象将绑定附加到 FrameworkElement。(继承自 FrameworkElement) |
下面给出常用的按钮事件。
Sr. No. | 事件和描述 |
---|---|
1 |
Click 单击按钮控件时发生。(继承自 ButtonBase) |
2 |
DataContextChanged 当 FrameworkElement.DataContext 属性的值更改时发生。(继承自 FrameworkElement) |
3 |
DragEnter 当输入系统报告以此元素为目标的底层拖动事件时发生。(继承自 UIElement) |
4 |
DragLeave 当输入系统报告以此元素为原点的底层拖动事件时发生。(继承自 UIElement) |
5 |
DragOver 当输入系统报告使用此元素作为潜在放置目标的基础拖动事件时发生。(继承自 UIElement) |
6 |
DragStarting 在启动拖动操作时发生。(继承自 UIElement) |
7 |
GotFocus 当 UIElement 获得焦点时发生。(继承自 UIElement) |
8 |
Holding 在此元素的命中测试区域上发生其他未处理的 Hold 交互时发生。(继承自 UIElement) |
9 |
IsEnabledChanged 当 IsEnabled 属性更改时发生。(继承自 Control) |
10 |
KeyDown 在 UIElement 具有焦点时按下键盘键时发生。(继承自 UIElement) |
11 |
KeyUp 在 UIElement 具有焦点时释放键盘键时发生。(继承自 UIElement) |
12 |
LostFocus 当 UIElement 失去焦点时发生。(继承自 UIElement) |
13 |
SizeChanged 当 ActualHeight 或 ActualWidth 属性更改 FrameworkElement 上的值时发生。(继承自 FrameworkElement) |
Sr. No. | 按钮和说明 |
---|---|
1 | HyperlinkButton
HyperlinkButton 不绘制标准按钮背景。相反,它只是呈现您提供的内容。 |
2 | ToggleButton & RepeatButton
只要按住按钮,RepeatButton 控件就会连续触发 Click 事件。ToggleButton 控件表示具有两种状态(单击或未单击)的按钮。 |
3 | CheckBox
用户可以选择(选中)或取消选择(取消选中)的控件。它提供用户可以选择的选项列表,例如要应用于应用程序的设置列表。 |
4 | RadioButton
RadioButton 是一个按钮,允许用户从一组选项中选择一个选项。 |
Silverlight – 内容模型
这些按钮为模型内容提供了一种内容形式。模型在控件中出现了很多。这个想法很简单。它将接受任何内容,而不仅仅是文本。如果您想创建一个真正奇特的按钮,您甚至可以在其中放置其他内容控件,例如文本框和按钮(并在其中嵌套静止元素)。这种接口是否有意义值得怀疑,但它是可能的。
让我们看一个带按钮的简单示例,按钮内的其他内容控件。
<UserControl x:Class = "ContentModel.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Button Margin = "3" Height = "70" Width = "215"> <Grid Margin = "5"> <Polygon Points = "100,25 125,0 200,25 125,50" Fill = "LightSteelBlue" /> <Polygon Points = "100,25 75,0 0,25 75,50" Fill = "LightGray"/> </Grid> </Button> </Grid> </UserControl>
当上面的代码编译执行后,你会看到下面的按钮。
范围控制
滚动条和滑块控件密切相关。它们都允许用户从特定范围中选择输入值。通常,这些控件表示不同的事物。滚动条通常用于将位置设置到阴囊区域,而滑块用于指定某些值或设置。这些只是约定;这些控件具有相似的行为和 API。
范围控件易于使用。您指定最小值和最大值以指示您希望滑块表示的值范围。该值属性将作为使用拖动而变化而变化。
Slider类的分层继承如下 –
下面给出了Slider的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Header 获取或设置控件标题的内容。 |
2 |
HeaderProperty 标识 Header 依赖项属性。 |
3 |
HeaderTemplate 获取或设置用于显示控件标题内容的 DataTemplate。 |
4 |
HeaderTemplateProperty 标识 HeaderTemplate 依赖项属性。 |
5 |
IntermediateValue 在用户与其交互时获取或设置 Slider 的值,然后将该值与刻度或步长值对齐。SnapsTo 属性指定滑块的值。 |
6 |
IntermediateValueProperty 标识 IntermediateValue 依赖项属性。 |
7 |
IsDirectionReversed 获取或设置一个值,该值指示值增加的方向。 |
8 |
IsDirectionReversedProperty 标识 IsDirectionReversed 依赖项属性。 |
9 |
IsThumbToolTipEnabled 获取或设置一个值,该值确定滑块值是否显示在 Slider 的 Thumb 组件的工具提示中。 |
10 |
IsThumbToolTipEnabledProperty 标识 IsThumbToolTipEnabled 依赖项属性。 |
11 |
Orientation 获取或设置 Slider 的方向。 |
12 |
OrientationProperty 标识方向依赖属性。 |
13 |
StepFrequency 获取或设置应为其创建步骤的值范围的值部分。 |
14 |
StepFrequencyProperty 标识 StepFrequency 依赖属性。 |
15 |
ThumbToolTipValueConverter 获取或设置将 Slider 的范围值转换为工具提示内容的转换器逻辑。 |
16 |
ThumbToolTipValueConverterProperty 标识 ThumbToolTipValueConverter 依赖项属性。 |
17 |
TickFrequency 获取或设置应为其创建刻度的值范围的增量。 |
18 |
TickFrequencyProperty 标识 TickFrequency 依赖属性。 |
19 |
TickPlacement 获取或设置一个值,该值指示在何处绘制与轨道相关的刻度线。 |
20 |
TickPlacementProperty 标识 TickPlacement 依赖项属性。 |
下面给出了Slider类中常用的事件。
Sr. No. | 事件和描述 |
---|---|
1 |
ManipulationCompleted 在 UIElement 上的操作完成时发生。(继承自 UIElement) |
2 |
ManipulationDelta 当输入设备在操作过程中改变位置时发生。(继承自 UIElement) |
3 |
ManipulationInertiaStarting 当输入设备在操作和惯性开始期间失去与 UIElement 对象的联系时发生。(继承自 UIElement) |
4 |
ManipulationStarted 当输入设备开始对 UIElement 进行操作时发生。(继承自 UIElement) |
5 |
ManipulationStarting 在首次创建操作处理器时发生。(继承自 UIElement) |
6 |
ValueChanged 当范围值改变时发生。(继承自 RangeBase) |
下面给出了Slider 类中常用的方法。
Sr. No. | 方法和说明 |
---|---|
1 |
OnManipulationCompleted 在 ManipulationCompleted 事件发生之前调用。(继承自 Control) |
2 |
OnManipulationDelta 在 ManipulationDelta 事件发生之前调用。(继承自 Control) |
3 |
OnManipulationInertiaStarting 在 ManipulationInertiaStarting 事件发生之前调用。(继承自 Control) |
4 |
OnManipulationStarted 在 ManipulationStarted 事件发生之前调用。(继承自 Control) |
5 |
OnManipulationStarting 在 ManipulationStarting 事件发生之前调用。(继承自 Control) |
6 |
OnMaximumChanged 当 Maximum 属性更改时调用。(继承自 RangeBase) |
7 |
OnMinimumChanged 当最小属性更改时调用。(继承自 RangeBase) |
8 |
OnValueChanged 触发 ValueChanged 路由事件。(继承自 RangeBase) |
9 |
SetBinding 使用提供的绑定对象将绑定附加到 FrameworkElement。(继承自 FrameworkElement) |
10 |
SetValue 在 DependencyObject 上设置依赖项属性的本地值。(继承自 DependencyObject) |
例子
让我们看一个简单的例子,其中添加了一个滑块和一个椭圆,滑块控制椭圆的宽度。
<UserControl x:Class = "SliderExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = " http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignWidth = "640" d:DesignHeight = "480"> <Grid x:Name = "LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition /> </Grid.RowDefinitions> <Slider Minimum = "1" Maximum = "400" Value = "1" ValueChanged = "Slider_ValueChanged" /> <Ellipse Grid.Row = "1" Fill = "Aqua" Width = "1" x:Name = "myEllipse" /> </Grid> </UserControl>
下面给出的是值更改事件实现是 C#。
using System.Windows; using System.Windows.Controls; namespace SliderExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { if (myEllipse != null) { myEllipse.Width = e.NewValue; } } } }
当上面的代码编译执行后,你会看到下面的输出。如您所见,当您从左向右移动滑块时,椭圆宽度会增加。
Silverlight – 列表框
Listbox 是一个控件,它向用户提供项目列表以供选择项目。用户可以一次从预定义的项目列表中选择一个或多个项目。在ListBox 中,多个选项始终对用户可见,无需任何用户交互。
列表框显示可滚动的项目列表。如果用户选择了一个项目,则所选项目的外观会发生变化以指示选择。它支持更广泛形式的内容模型和按钮。按钮和列表框之间的主要区别在于按钮包含单个内容,而列表框允许列表中的每个项目。
ListBox 类的层次继承如下 –
下面给出了ListBox类的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
Background 获取或设置提供控件背景的画笔。(继承自 Control) |
2 |
BorderThickness 获取或设置控件的边框粗细。(继承自 Control) |
3 |
FontFamily 获取或设置用于在控件中显示文本的字体。(继承自 Control) |
4 |
FontSize 获取或设置此控件中文本的大小。(继承自 Control) |
5 |
FontStyle 获取或设置呈现文本的样式。(继承自 Control) |
6 |
FontWeight 获取或设置指定字体的粗细。(继承自 Control) |
7 |
Foreground 获取或设置描述前景色的画笔。(继承自 Control) |
8 |
GroupStyle 获取定义每个级别组的外观的 GroupStyle 对象的集合。(继承自 ItemsControl) |
9 |
Height 获取或设置 FrameworkElement 的建议高度。(继承自 FrameworkElement) |
10 |
HorizontalAlignment 获取或设置在布局父级(如面板或项目控件)中组合时应用于 FrameworkElement 的水平对齐特征。(继承自 FrameworkElement) |
11 |
IsEnabled 获取或设置一个值,该值指示用户是否可以与控件交互。(继承自 Control) |
12 |
Item 获取用于生成控件内容的集合。(继承自 ItemsControl) |
13 |
ItemsSource 获取或设置用于生成 ItemsControl 内容的对象源。(继承自 ItemsControl) |
14 |
Margin 获取或设置 FrameworkElement 的外边距。(继承自 FrameworkElement) |
15 |
Name 获取或设置对象的标识名称。当 XAML 处理器从 XAML 标记创建对象树时,运行时代码可以通过此名称引用 XAML 声明的对象。(继承自 FrameworkElement) |
16 |
Opacity 获取或设置对象的不透明度程度。(继承自 UIElement) |
17 |
SelectedIndex 获取或设置所选项目的索引。(继承自选择器) |
18 |
SelectedItem 获取或设置所选项目。(继承自选择器) |
19 |
SelectedValue 获取或设置选中项的值,通过 SelectedValuePath 获取。(继承自选择器) |
20 |
Style 获取或设置在布局和呈现期间应用于此对象的实例 Style。(继承自 FrameworkElement) |
21 |
VerticalAlignment 获取或设置在父对象(如面板或项目控件)中组合时应用于 FrameworkElement 的垂直对齐特征。(继承自 FrameworkElement) |
22 |
Width 获取或设置 FrameworkElement 的宽度。(继承自 FrameworkElement) |
下面给出了ListBox最常用的事件。
Sr. No. | 事件和描述 |
---|---|
1 |
DragEnter 当输入系统报告以此元素为目标的底层拖动事件时发生。(继承自 UIElement) |
2 |
DragLeave 当输入系统报告以此元素为原点的底层拖动事件时发生。(继承自 UIElement) |
3 |
DragOver 当输入系统报告使用此元素作为潜在放置目标的基础拖动事件时发生。(继承自 UIElement) |
4 |
DragStarting 在启动拖动操作时发生。(继承自 UIElement) |
5 |
Drop 当输入系统报告使用此元素作为放置目标的基础放置事件时发生。(继承自 UIElement) |
6 |
DropCompleted 在拖放操作结束时发生。(继承自 UIElement) |
7 |
GotFocus 当 UIElement 获得焦点时发生。(继承自 UIElement) |
8 |
IsEnabledChanged 当 IsEnabled 属性更改时发生。(继承自 Control) |
9 |
KeyDown 在 UIElement 具有焦点时按下键盘键时发生。(继承自 UIElement) |
10 |
KeyUp 在 UIElement 具有焦点时释放键盘键时发生。(继承自 UIElement) |
11 |
LostFocus 当 UIElement 失去焦点时发生。(继承自 UIElement) |
12 |
SelectionChanged 在当前选定的项目更改时发生。(继承自选择器) |
13 |
SizeChanged 当 ActualHeight 或 ActualWidth 属性更改 FrameworkElement 上的值时发生。(继承自 FrameworkElement) |
下面给出了ListBox最常用的方法。
Sr. No. | 方法和说明 |
---|---|
1 |
Arrange 定位子对象并确定 UIElement 的大小。为其子元素实现自定义布局的父对象应从其布局覆盖实现中调用此方法以形成递归布局更新。(继承自 UIElement) |
2 |
FindName 检索具有指定标识符名称的对象。(继承自 FrameworkElement) |
3 |
Focus 尝试将焦点设置在控件上。(继承自 Control) |
4 |
GetValue 从 DependencyObject 返回依赖项属性的当前有效值。(继承自 DependencyObject) |
5 |
IndexFromContainer 返回具有指定生成容器的项的索引。(继承自 ItemsControl) |
6 |
OnDragEnter 在 DragEnter 事件发生之前调用。(继承自 Control) |
7 |
OnDragLeave 在 DragLeave 事件发生之前调用。(继承自 Control) |
8 |
OnDragOver 在 DragOver 事件发生之前调用。(继承自 Control) |
9 |
OnDrop 在 Drop 事件发生之前调用。(继承自 Control) |
10 |
OnKeyDown 在 KeyDown 事件发生之前调用。(继承自 Control) |
11 |
OnKeyUp 在 KeyUp 事件发生之前调用。(继承自 Control) |
12 |
OnLostFocus 在 LostFocus 事件发生之前调用。(继承自 Control) |
13 |
ReadLocalValue 如果设置了本地值,则返回依赖项属性的本地值。(继承自 DependencyObject) |
14 |
SetBinding 使用提供的绑定对象将绑定附加到 FrameworkElement。(继承自 FrameworkElement) |
15 |
SetValue 在 DependencyObject 上设置依赖项属性的本地值。(继承自 DependencyObject) |
让我们看一个简单的例子,其中在ListBox中添加了不同的 UI 元素。
<UserControl x:Class = "ListBoxExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignWidth = "640" d:DesignHeight = "480"> <Grid x:Name = "LayoutRoot"> <ListBox x:Name = "myList"> <TextBlock Text = "First item" /> <Button Content = "Second item" /> <Path Fill = "Blue" Data = "M4,0 l-4,10 8,0z M15,0 l-4,10 8,0z M26,0 l4,10 8,0z" Margin = "10" /> <StackPanel Orientation = "Horizontal"> <Ellipse Fill = "Red" Height = "30" Width = "100" /> <TextBlock Text = "Name: " /> <TextBox Width = "200" /> </StackPanel> <TextBlock Text = "More..." /> </ListBox> </Grid> </UserControl>
下面给出的是 C# 实现。
using System.Windows.Controls; namespace ListBoxExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); myList.Items.Add("String entry"); myList.Items.Add(new Button { Content = "Content entry" }); } } }
编译并执行上述代码后,您将看到一个列表框,其中包含图形文本和一个可编辑字段,您可以在其中键入文本。
Sr. No. | 控制和描述 |
---|---|
1 | Calendar & DatePicker
Calendar & DatePicker 表示一个控件,它使用户能够通过使用可视日历显示来选择日期。它提供了一些使用鼠标或键盘的基本导航。 |
2 | TabControl
一种将项目放入单独选项卡并允许用户一次仅查看一个选项卡的容器。它允许用户通过单击选项卡标题从许多不同的视图中进行选择。 |
3 | Popup
此类在现有内容之上,在应用程序窗口的边界内显示内容。它是对其他内容的临时显示。 |
4 | ToolTip
工具提示表示创建弹出窗口的控件,该窗口显示 GUI 中元素的信息。Silverlight 允许您将工具提示附加到任何控件。 |
Silverlight – 模板
一个模板描述了整体外观和控件的视觉外观。对于每个控件,都有一个与之关联的默认模板,它为该控件提供外观。
在 WPF 应用程序中,当您想要自定义控件的视觉行为和视觉外观时,您可以轻松创建自己的模板。
一些重要的功能是 –
-
所有 UI 元素都具有某种外观和行为,例如Button具有外观和行为。
-
单击事件或鼠标悬停事件是响应单击和悬停而触发的行为,并且按钮的默认外观可以通过控制模板进行更改。
让我们再看一个简单的例子,其中一个按钮是用模板定义的。
<UserControl x:Class = "ButtonTemplate.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignWidth = "640" d:DesignHeight = "480"> <Grid x:Name = "LayoutRoot" HorizontalAlignment = "Center" VerticalAlignment = "Center"> <Button Height = "100" Width = "100" Content = "Click!" HorizontalContentAlignment = "Left" Click = "button_Click"> <Button.Template> <ControlTemplate TargetType = "Button"> <Grid> <Ellipse Fill = "Gray" Stroke = "Black" StrokeThickness = "3" Margin = "-64,0,0,0" /> <ContentPresenter HorizontalAlignment = "{TemplateBinding HorizontalContentAlignment}" VerticalAlignment = "Center" Content = "{TemplateBinding Content}" /> </Grid> </ControlTemplate> </Button.Template> </Button> </Grid> </UserControl>
当上面的代码编译执行后,你会看到下面的输出。
连接模板
我们想要模板化的所有控件功能都带有模板绑定。有些方面稍微复杂一些。例如,无论何时您拥有某种形式的内容模型,仅靠模板绑定是不够的,就像您在按钮上看到的那样。我们还必须使用内容展示器,如上例所示。
Silverlight – 视觉状态
如果您的用户能够判断应用程序的哪一部分可能响应输入,那就太好了。在某种程度上,这可以通过使按钮看起来像按钮来实现。如果某些东西看起来可以点击,那很可能就是。
然而,现代用户界面设计中的一个约定是,当鼠标移到他们上面时,用户界面元素也应该通过改变他们的父母来表示愿意做出响应。
例如,内置按钮控件会在鼠标移过时略微改变其背景,以暗示它是交互式的,然后在单击时进一步更改父控件以使其看起来像被选中。几乎所有控件都需要这样做,设计师需要一种方法来创建和编辑动画以实现它。
国家和国家集团
让我们看一个视觉状态的例子。考虑一个复选框。它可能是未选中或选中的,如果您选择,它可以支持第三种不确定状态。对于所有三种情况,控件都需要看起来不同。因此,我们有三个视觉状态。
为了证明它已准备好响应用户输入,当鼠标移到复选框上时它的外观会发生轻微的变化,当鼠标停留在那里时它会进一步变化。如果复选框被禁用,则必须考虑第四种状态,它看起来很棒并且表示它不会响应用户输入。
所以,我们这里还有另外四个州。在任何给定时间,复选框的视觉状态必须是Normal、Mouse over、Checked或Disabled。同时,它必须是选中的、未选中的或不确定的。
视觉状态管理器
由于其模板定义了控件的外观,因此模板需要定义每个视觉状态发生的情况。到目前为止,我们查看的模板不包含此类信息。因此,控件的外观保持静态,无论其当前状态如何。
要将视觉状态添加到模板,首先要添加属性元素。
-
您可以为视觉状态处理做的最简单的事情是定义在控件进入特定状态时将运行的动画。
-
每当控件更改状态时,它们都会通知视觉状态管理器类。
-
然后,视觉状态管理器查看模板的这一部分并找出要运行的动画。
-
因此,当复选框进入鼠标overstate 时,此动画将运行,更改模板某些部分的颜色。
让我们看一个简单的例子,它使用视觉状态机制为反映状态变化的复选框制作自定义模板。
下面给出了具有视觉状态的复选框的自定义模板的 XAML 代码。
<UserControl xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" x:Class = "CheckboxVisualState.Page" Width = "640" Height="480" xmlns:vsm = "clrnamespace:System.Windows;assembly = System.Windows" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d"> <UserControl.Resources> <ControlTemplate x:Key = "CheckBoxControlTemplate1" TargetType = "CheckBox"> <Grid> <vsm:VisualStateManager.VisualStateGroups> <vsm:VisualStateGroup x:Name = "FocusStates"> <vsm:VisualState x:Name = "ContentFocused"/> <vsm:VisualState x:Name = "Focused"/> <vsm:VisualState x:Name = "Unfocused"/> </vsm:VisualStateGroup> <vsm:VisualStateGroup x:Name = "CommonStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration = "00:00:00.5000000"/> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name = "MouseOver"> <Storyboard> <ColorAnimationUsingKeyFrames BeginTime = "00:00:00" Duration = "00:00:00.0010000" Storyboard.TargetName = "background" Storyboard.TargetProperty = "(Shape.Fill). (SolidColorBrush.Color)"> <SplineColorKeyFrame KeyTime = "00:00:00" Value = "#FFFF0000"/> </ColorAnimationUsingKeyFrames> </Storyboard> </vsm:VisualState> <vsm:VisualState x:Name = "Pressed"> <Storyboard> <ColorAnimationUsingKeyFrames BeginTime = "00:00:00" Duration = "00:00:00.0010000" Storyboard.TargetName = "background" Storyboard.TargetProperty = "(Shape.Fill). (SolidColorBrush.Color)"> <SplineColorKeyFrame KeyTime = "00:00:00" Value = "#FFCEFF00"/> </ColorAnimationUsingKeyFrames> </Storyboard> </vsm:VisualState> <vsm:VisualState x:Name = "Disabled"/> <vsm:VisualState x:Name = "Normal"/> </vsm:VisualStateGroup> <vsm:VisualStateGroup x:Name = "CheckStates"> <vsm:VisualStateGroup.Transitions> <vsm:VisualTransition GeneratedDuration = "00:00:00.5000000"/> </vsm:VisualStateGroup.Transitions> <vsm:VisualState x:Name = "Checked"> <Storyboard> <DoubleAnimationUsingKeyFrames BeginTime = "00:00:00" Duration = "00:00:00.0010000" Storyboard.TargetName = "checkPath" Storyboard.TargetProperty = "(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime = "00:00:00" Value = "1"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </vsm:VisualState> <vsm:VisualState x:Name = "Unchecked"/> <vsm:VisualState x:Name = "Indeterminate"/> </vsm:VisualStateGroup> </vsm:VisualStateManager.VisualStateGroups> <Grid.ColumnDefinitions> <ColumnDefinition Width = "Auto"/> <ColumnDefinition Width = "3.61782296696066"/> <ColumnDefinition Width = "Auto"/> </Grid.ColumnDefinitions> <Canvas Height = "50" HorizontalAlignment = "Left" VerticalAlignment = "Top" Width = "50"> <Rectangle Height = "33.746" x:Name = "background" Width = "33.746" Canvas.Left = "8.452" Canvas.Top = "7.88" Fill = "#FFFFFFFF" Stroke = "#FF000000" RadiusX = "5.507" RadiusY = "5.507"/> <Path Height = "40.25" x:Name = "checkPath" Width = "39.75" Opacity = "0" Canvas.Left = "5.959" Canvas.Top = "7.903" Stretch = "Fill" Stroke = "#FF1F9300" StrokeThickness = "3" Data = "M1.5,1.5 C15.495283,8.7014561 27.056604,18.720875 33.75,33.75 M36,3.75 C22.004717,10.951456 10.443395,20.970875 3.7499986,36"/> </Canvas> <ContentPresenter HorizontalAlignment = "Left" Margin = "{TemplateBinding Padding}" VerticalAlignment = "{TemplateBinding VerticalContentAlignment}" Grid.Column = "2" Grid.ColumnSpan = "1" d:LayoutOverrides = "Height"/> </Grid> </ControlTemplate> </UserControl.Resources> <Grid x:Name = "LayoutRoot" Background = "White" > <CheckBox HorizontalAlignment = "Left" Margin = "52.5410003662109,53.5970001220703,0,0" VerticalAlignment = "Top" Template = "{StaticResource CheckBoxControlTemplate1}" Content = "CheckBox"/> </Grid> </UserControl>
上述代码编译执行后,会看到如下网页,其中包含一个复选框。
当光标进入复选框区域时,它会改变状态。
当您单击复选框时,您将看到以下状态。
我们建议您执行上面的示例以更好地理解。
Silverlight – 数据绑定
数据绑定是 Silverlight 应用程序中的一种机制,它为 Windows 运行时应用程序使用部分类来显示和与数据交互提供了一种简单易行的方法。在这种机制中,数据的管理与数据的显示方式完全分离。数据绑定允许数据在 UI 元素和用户界面上的数据对象之间流动。当建立绑定并且数据或您的业务模型发生变化时,它将自动将更新反映到 UI 元素,反之亦然。也可以不绑定到标准数据源,而是绑定到页面上的另一个元素。
数据绑定有以下两种类型 –
- 单向数据绑定
- 双向数据绑定
单向数据绑定
在单向数据绑定中,数据从其源(即保存数据的对象)绑定到其目标(即显示数据的对象)。
让我们看一个单向数据绑定的简单示例。
下面给出的是 XAML 代码,其中使用一些属性创建了两个标签、两个文本框和一个按钮。
<UserControl x:Class = "DataBinding.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition Height = "Auto" /> <RowDefinition Height = "*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width = "Auto" /> <ColumnDefinition Width = "200" /> </Grid.ColumnDefinitions> <TextBlock Name = "nameLabel" Margin = "2">Name:</TextBlock> <TextBox Name = "nameText" Grid.Column = "1" Margin = "2" Text = "{Binding Name, Mode=OneWay}"/> <TextBlock Name = "ageLabel" Margin = "2" Grid.Row = "1">Age:</TextBlock> <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin="2" Text = "{Binding Age, Mode = OneWay}"/> <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2"> <Button Content = "_Show..." Click = "Button_Click" /> </StackPanel> </Grid> </UserControl>
我们观察以下事项 –
-
两个文本框的文本属性都绑定到“ Name ”和“ Age ”,它们是Person类的类变量,如下所示。
-
在Person类中,我们只有两个变量Name和Age,其对象在MainPage类中初始化。
-
在 XAML 代码中,我们绑定到属性Name和 Age,但我们没有选择哪个属性属于该对象。
-
一种简单的方法是将一个对象分配给DataContext,我们在MainPage构造函数的 C# 代码中绑定其属性,如下所示。
using System.Windows; using System.Windows.Controls; namespace DataBinding { public partial class MainPage : UserControl { Person person = new Person { Name = "Salman", Age = 26 }; public MainPage() { InitializeComponent(); this.DataContext = person; } private void Button_Click(object sender, RoutedEventArgs e) { string message = person.Name + " is " + person.Age; MessageBox.Show(message); } } public class Person { private string nameValue; public string Name { get { return nameValue; } set { nameValue = value; } } private double ageValue; public double Age { get { return ageValue; } set { if (value != ageValue) { ageValue = value; } } } } }
让我们运行这个应用程序,您可以立即在您的网页中看到我们已成功绑定到该 Person 对象的 Name 和 Age 。
当您按下Show按钮时,它将在消息框中显示姓名和年龄。
让我们在上面的对话框中更改名称和年龄。
现在,如果您单击“显示”按钮,它将再次显示相同的消息。
这是因为数据绑定模式在 XAML 代码中设置为单向。要显示更新的消息,您需要了解双向数据绑定。
双向数据绑定
在双向绑定中,用户能够通过用户界面修改数据并在源中更新该数据。如果在用户查看视图时源发生更改,您希望更新视图。
让我们看一下相同的示例,但仅将 XAML 代码中的绑定模式从单向绑定更改为双向绑定,如下所示。
<UserControl x:Class = "DataBinding.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition Height = "Auto" /> <RowDefinition Height = "*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width = "Auto" /> <ColumnDefinition Width = "200" /> </Grid.ColumnDefinitions> <TextBlock Name = "nameLabel" Margin = "2">_Name:</TextBlock> <TextBox Name = "nameText" Grid.Column = "1" Margin = "2" Text = "{Binding Name, Mode=TwoWay}"/> <TextBlock Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</TextBlock> <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2" Text = "{Binding Age, Mode = TwoWay}"/> <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2"> <Button Content = "_Show..." Click = "Button_Click" /> </StackPanel> </Grid> </UserControl>
让我们再次运行此应用程序,您可以看到相同的输出。
让我们在上面的对话框中更改名称和年龄。
现在,如果您单击“显示”按钮,它将显示更新的消息。
Silverlight – 浏览器集成
在本章中,我们将看到 Silverlight 应用程序如何使用浏览器集成支持与网页结合工作。
我们可以通过以下两种方式探索 Silverlight 与浏览器的集成 –
-
在浏览器中运行的 JavaScript 代码可以访问 Silverlight 应用程序中的功能。
-
Silverlight 能够为对象提供 JavaScript 包装器。由于JavaScript 对象的 Silverlight .NET包装器,您在 Silverlight 插件中运行的.NET代码可以访问 HTML DOM 和其他浏览器脚本功能。
我们将看到基于浏览器的软件应用程序如何在客户端上持久存储信息。
Silverlight 和 HTML
就 HTML 世界而言,Silverlight 内容只是一个元素。这对于布局来说是正确的。整个 Silverlight 插件及其所有内容看起来只是一个对象元素。
你必须记住 –
-
Silverlight 不是 HTML 的替代品,它旨在补充它。因此,能够访问 DOM 中的另一个元素是很重要的。
-
它使您能够在适当的情况下使用 Silverlight。
-
在一个主要使用 HTML 的页面上,Silverlight 与浏览器世界的集成不仅仅是作为一个 DOM 元素存在,受制于正常的 HTML 布局。
访问 DOM
Silverlight 内容必须能够完全参与网页。因此,它应该能够访问 HTML DOM。Silverlight 提供将浏览器脚本对象包装为 Dot Net 对象的桥对象,即系统中的Script 对象类。浏览器命名空间提供了一些方法,让您可以在浏览器脚本对象上读取和写入属性并将函数投入使用。
您首先需要一种方法来获取 Script 对象。Silverlight 提供了一个 HTML 页面类,使您可以访问各种页面的功能,例如 Script 对象。
让我们看一个简单的例子,在这个例子中,我们有一个简单的脚本来创建一个具有几个属性的对象。其中一些只是值,其中一些是函数。
<script type = "text/javascript"> myJsObject = { answer: 42, message: "Hello, world", modifyHeading: function(title) { document.getElementById('heading').innerHTML = title; }, performReallyComplexCalculation: function(x, y) { return x + y; } }; </script>
下面给出了添加按钮的 XAML 代码。
<UserControl x:Class = "DomAccess.Page" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Width = "400" Height = "300"> <Grid x:Name = "LayoutRoot" Background = "White"> <Button x:Name = "useDomButton" Content = "Use DOM" Width = "75" Height = "30" Click = "useDomButton_Click" /> </Grid> </UserControl>
这是调用在 HTML 文件中创建的脚本的按钮单击实现。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Browser; using System.Diagnostics; namespace DomAccess { public partial class Page : UserControl { public Page() { InitializeComponent(); } private void useDomButton_Click(object sender, RoutedEventArgs e) { ScriptObject myJsObject = HtmlPage.Window.GetProperty("myJsObject") as ScriptObject; string[] propertyNames = { "answer", "message", "modifyHeading", "performReallyComplexCalculation" }; foreach (string propertyName in propertyNames) { object value = myJsObject.GetProperty(propertyName); Debug.WriteLine("{0}: {1} ({2})", propertyName, value, value.GetType()); } object result = myJsObject.Invoke("performReallyComplexCalculation", 11, 31); HtmlElement h1 = HtmlPage.Document.GetElementById("heading"); h1.SetProperty("innerHTML", "Text from C# (without JavaScript's help)"); h1.SetStyleAttribute("height", "200px"); } } }
下面给出的是完整的 HTML 文件。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns = "http://www.w3.org/1999/xhtml" > <!-- saved from url = (0014)about:internet --> <head> <title>DomAccess</title> <script type = "text/javascript"> myJsObject = { answer: 42, message: "Hello, world", modifyHeading: function(title) { document.getElementById('heading').innerHTML = title; }, performReallyComplexCalculation: function(x, y) { return x + y; } }; </script> <style type = "text/css"> html, body { height: 100%; overflow: auto; } body { padding: 0; margin: 0; } #silverlightControlHost { height: 100%; } </style> <script type = "text/javascript" src = "Silverlight.js"></script> <script type = "text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n" ; errMsg += "Code: "+ iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; } throw new Error(errMsg); } </script> </head> <body> <!-- Runtime errors from Silverlight will be displayed here. This will contain debugging information and should be removed or hidden when debugging is completed --> <div id = 'errorLocation' style = "font-size: small;color: Gray;"></div> <h1 id = 'heading'></h1> <div id = "silverlightControlHost"> <object data = "data:application/x-silverlight-2," type = "application/x-silverlight-2" width = "100%" height = "100%"> <param name = "source" value = "ClientBin/DomAccess.xap"/> <param name = "onerror" value = "onSilverlightError" /> <param name = "background" value = "white" /> <param name = "minRuntimeVersion" value = "2.0.30923.0" /> <param name = "autoUpgrade" value = "true" /> <a href = "http://go.microsoft.com/fwlink/?LinkID=124807" style = "text-decoration: none;"> <img src = "http://go.microsoft.com/fwlink/?LinkId=108181" alt = "Get Microsoft Silverlight" style = "border-style: none"/> </a> </object> <iframe style = 'visibility:hidden;height:0;width:0;border:0px'></iframe> </div> </body> </html>
编译并执行上述代码后,您将在输出窗口中看到从 HTML 文件中获取的所有值。
Silverlight – 浏览器外应用程序
我们现在将探索 Silverlight 对可以安装在最终用户机器上的应用程序的支持,以便像普通的 Windows 应用程序一样在 Web 浏览器之外运行。您可能希望应用程序能够在浏览器外运行的三个主要原因 –
- 相互作用
- 离线
- 提升信任度
相互作用
它可以实现更好的交互设计。Web 的导航模型不是特别适合某些应用程序。例如,地址栏和返回按钮可能会浪费空间,而且毫无用处。
Silverlight 的重要性如下所示 –
-
Web 应用程序可以使用客户端技术(例如 Silverlight、Flash 或 AJAX)为单个页面提供持续更新,或许无需导航到其他页面。
-
在某些应用程序中,用户可能会在浏览器认为是单个页面的内容上花费几分钟甚至几个小时。
-
对于此类应用程序,“后退”按钮最终会产生相当令人惊讶的退出应用程序效果,因为它会将您转回到进入应用程序之前所在的任何页面。
-
显然,非 Web 类应用程序通常通过运行在浏览器之外更好地提供服务,因为这摆脱了 Chrome 浏览器。通常,可用性不是浏览器耗尽的唯一原因。
离线
使用此功能的另一个原因是启用离线执行。当为浏览器外操作安装 Silverlight 应用程序时,它会被复制到本地计算机上的每个用户存储库中,并通过用于启动应用程序的常用操作系统机制(例如 Windows 上的“开始”菜单)变得可用。
-
即使用户没有互联网连接,该应用程序也将可用。
-
显然,这仅对不完全依赖服务器端信息的应用程序有帮助。
-
例如,如果没有网络连接,包裹递送服务的自动跟踪应用程序就没有多大用处。
-
对于某些应用程序,在偶尔出现连接故障期间继续工作的能力非常有用。
提升信任度
Silverlight 的第 4 版增加了对受信任应用程序的支持。Silverlight 的安全沙箱通常会阻止某些特权操作,例如访问用户的文件。
但是,浏览器外的应用程序可能会请求提升。如果用户批准了该请求,应用程序就能够完成任何普通 Windows 应用程序能够完成的更多工作,例如使用 COM 自动化或自定义窗口边框。
在浏览器内运行的应用程序永远不会被信任,因此如果您想使用这些功能,您必须编写一个浏览器外的应用程序。
启用OOB
我们如何编写浏览器外应用程序?这很容易。我们必须在 Silverlight 的项目属性中更改单个设置,它只会向AppManifest.xaml添加一个合适的设置。
让我们看看它是如何工作的。
-
当您的清单指示支持浏览器外执行时,这没有初始效果。该应用程序将像往常一样在浏览器中运行。
-
但是,如果用户右键单击,标准 Silverlight ContextMenu 会提供一个额外的项目来在计算机上安装应用程序。
-
如果用户选择该项目,则会出现一个对话框,要求确认。它还询问是否可以从“开始”菜单、桌面或两者访问应用程序。
-
您不必依赖上下文菜单。您还可以提供一个按钮,用户可以单击该按钮来安装应用程序,因为有一个 API,您可以调用它来启动安装。
-
当您以编程方式开始安装时,用户仍会看到该对话框。未经用户同意,您不能安装您的应用。
Silverlight 应用程序
这是一个非常简单的 Silverlight 应用程序。下面给出的是它的 XAML 代码。
<UserControl x:Class = "SimpleOob.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Border BorderBrush = "Blue" BorderThickness = "4" CornerRadius = "20" > <Border.Background> <LinearGradientBrush StartPoint = "0,0" EndPoint = "0,1"> <GradientStop Offset = "0.0" Color = "White" /> <GradientStop Offset = "0.15" Color = "#cef" /> <GradientStop Offset = "1.0" Color = "White" /> </LinearGradientBrush> </Border.Background> <TextBlock HorizontalAlignment = "Center" VerticalAlignment = "Center" Text = "Silverlight Application" TextOptions.TextHintingMode = "Animated" TextAlignment = "Center" TextWrapping = "Wrap" FontSize = "72" FontFamily = "Trebuchet MS" > <TextBlock.Effect> <DropShadowEffect Color = "#888" /> </TextBlock.Effect> </TextBlock> </Border> </Grid> </UserControl>
步骤 1 – 要启用浏览器外执行,请转到项目的Properties,然后单击 Silverlight 选项卡。我们需要做的就是 –在浏览器中选中启用正在运行的应用程序复选框。
如果您运行此应用程序,您会注意到您根本不会获得 Web 浏览器。
事实上,Visual Studio 已经代表你做出了决定。当您启用浏览器外执行时,它不公平地更改了您的调试设置。
第 2 步– 因此,在解决方案资源管理器中,注意 Silverlight 项目现在以粗体显示,表明它是一个启动项目。
以前不是这样。它曾经是网络项目。现在,我们不希望那样,因为我们想展示该复选框如何为最终用户更改内容。
第 3 步– 我们将网络项目设置回启动项目。
第 4 步– 再次运行该应用程序,您将看到该应用程序现在又回到了浏览器中。
步骤 5 – 右键单击网页。您会在上下文菜单中注意到通常的 Silverlight 条目,以及要安装的额外项目。
步骤 6 – 当您选择第二个选项时,安装应用程序对话框如下所示。
请注意,它显示了应用程序来自的网站的根 URL。我们使用的是 Visual Studio 提供的本地调试 Web 服务器,这就是为什么它说 localhost。
步骤 7 – 单击OK,应用程序在与浏览器分开的自己的窗口中运行。
可能很自然地认为该窗口以某种方式归浏览器所有或连接到浏览器,但事实并非如此。你可以关闭浏览器,这个窗口会一直存在。更重要的是,您可以关闭此窗口,然后完全不使用浏览器重新运行应用程序。
步骤 8 – 如果您在“开始”菜单中打开“搜索”对话框并开始键入应用程序名称,它会像任何普通的 Windows 应用程序一样显示。
第 9 步– 您可以在浏览器不在视线范围内的情况下运行它。
卸载应用程序
应用程序上的默认上下文菜单提供了一种简单的方法来做到这一点。用户可以合理地期望像卸载任何其他应用程序一样卸载它。
您也可以通过右键单击网页并选择删除此应用程序…来删除。
带外设置
尽管我们只需要更改一个设置即可启用浏览器外操作,但实际上,您通常需要做更多的事情。该AppManifest.xaml文件可以包含相关的几个设置外的浏览器操作,即我们通常通过Visual Studio配置。
您可能已经注意到,当您选中复选框以启用运行 out-ofbrowser 时,Visual Studio 启用了一个标记为Out-of-Browser Settings的按钮。
让我们通过单击按钮来看看它。它将产生以下对话框。
-
我们可以配置的第一件事是显示为Window Title的文本。
-
我们还可以选择修复窗口尺寸和位置,但我们暂时将它们保留为自动。
-
此快捷方式名称会出现在“开始”菜单中,以及安装应用程序后的桌面链接中。
-
它也是出现在上下文菜单和安装应用程序对话框中的文本。
-
当我将鼠标悬停在快捷方式上时,此应用程序说明会出现在工具提示中。
-
我们可以提供各种尺寸的图标。这些必须内置到您的项目中。
应用程序、资源和部署
在本章中,我们将着眼于创建和部署应用程序及其所需资源的常见问题。
加载插件
运行 Silverlight 应用程序的最低要求是托管包含用于加载 Silverlight 插件的对象标记的网页,以及编译的 Silverlight 内容本身。
如您所见,我们在object标签中使用了param标签来指向内容。
-
HTML <Object> 标签
我们还可以传入其他参数来控制功能,例如下载内容时显示的用户界面、发生错误时运行的 JavaScript 代码以及未安装 Silverlight 时显示的回退内容。
HTML 中的 <对象>
这是加载一些 Silverlight 内容的示例对象标记。您之前已经看到了这一点,但我们将从对象标签本身的属性开始,更详细地了解一些事情。
类型属性
type 属性包含将其标识为 Silverlight 元素的 MIME 类型。这就是浏览器如何知道我们正在使用什么样的嵌入内容。object 标签非常灵活。它不仅适用于插件。您可以使用它来托管嵌入的图像或 HTML,以及基于插件的内容,例如 Silverlight 或 Flash。
如果安装了 Silverlight 插件,这将加载它。如果没有,浏览器的标准格式行为是在 object 标签内呈现任何 HTML 内容,就好像 object 和 param 标签不存在一样。
<object data = "data:application/x-silverlight-2," type = "application/x-silverlight-2" width = "100%" height = "100%"> <param name = "source" value = "ClientBin/DataBinding.xap"/> <param name = "onError" value = "onSilverlightError" /> <param name = "background" value = "white" /> <param name = "minRuntimeVersion" value = "5.0.61118.0" /> <param name = "autoUpgrade" value = "true" /> <a href = "http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style = "textdecoration:none"> <img src = "http://go.microsoft.com/fwlink/?LinkId=161376" alt = "Get Microsoft Silverlight" style = "border-style:none"/> </a> </object>
数据属性
下一个属性,数据,不太明显。末尾的逗号意味着在那里。一些重要的功能是 –
-
此属性在技术上不是必需的,但 Microsoft 建议您添加它,因为某些 Web 浏览器在加载插件时会出现相当令人惊讶的行为。
-
该对象的标签被设计为主机嵌入的内容,这样浏览器就想到一个二进制字符串参与,位图文件或视频或音频流,或者什么的。
-
您通常希望在 data 属性中放置一个 URL,浏览器会下载该数据,并将其传递给插件。
-
data 属性需要一个 URI,通常它会指向一些数据,例如 JPEG 文件,但在这里,我们使用了一个稍微不寻常的 URI 方案。
<param> 标签
我们在对象中有各种param标签,从源param 开始。
<param name = "source" value = "ClientBin/DataBinding.xap"/>
它提供插件从何处下载 Silverlight 内容。
您应该提供一个 JavaScript 错误处理程序。如果下载过程失败,这将被调用。一旦 Silverlight 代码启动并运行,如果抛出未处理的异常,它也会被调用。
<param name = "onError" value = "onSilverlightError" />
因此,它不仅适用于负载故障。您还应该指定代码所需的最低 Silverlight 版本。
Microsoft 鼓励用户保持最新状态,因此一旦机器安装了 Silverlight 插件,新版本将通过 Windows 更新提供,但用户总是可能运行比您需要的旧版本.
<param name = "minRuntimeVersion" value = "5.0.61118.0" /> <param name = "autoUpgrade" value = "true" />
此minRuntimeVersion参数可让您说明您需要哪个版本。如果安装的版本较旧,则将调用 onError 处理程序。
Silverlight 将数字错误代码传递给错误处理 JavaScript 函数,并且有一个明显的错误代码“ 8001 ”,它恰好表示插件已过期。
您可以编写 JavaScript 代码来响应问题,或者您可以让插件尝试为您升级。
在这里,autoUpgrade参数设置为“ True ”,这意味着如果安装的插件已过期,Silverlight 将自动显示一条消息,告诉用户需要更新的版本,并提供为他们安装。
回退 HTML 内容
如果未安装 Silverlight,则在 param 标记之后是要使用的回退 HTML 内容。
MIME类型未知的对象标签的标准浏览器行为是,就好像对象和参数标签根本不存在一样。因此,这个标签及其内容将显示在没有 Silverlight 插件的系统中。
<a href = "http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style = "text-decoration:none"> <img src = "http://go.microsoft.com/fwlink/?LinkId=161376" alt = "Get Microsoft Silverlight" style = "border-style:none"/> </a>
请注意go.microsoft.com站点的两个 URL 、一个超链接和一个图像。
图像链接解析为带有一些 Silverlight 品牌和一些提供安装 Silverlight 的文本的位图。超链接的端点是适度智能的。服务器检查用户代理以决定重定向的位置。
它可能会返回 Silverlight 安装可执行文件,或者如果用户在不受支持的平台上,它会将浏览器定向到包含有关 Silverlight 的信息的页面。
Silverlight.js
有一种替代 HTML 对象标记的方法用于加载 Silverlight 内容。Microsoft 提供了一个名为Silverlight.js的 JavaScript 文件,允许从浏览器脚本管理加载过程。
当您创建 Web 项目以托管新创建的 Silverlight 项目时,Visual Studio 会添加一个副本。Silverlight SDK 还包含此文件的副本。
Silverlight.js的主要优点是它在未安装 Silverlight 时提供了更大的灵活性。
XAML 资源
Silverlight 还提供了一种在 XAML 中创建对象资源的机制。通常通过 XAML 更正某些类型的对象,您可能希望能够在应用程序的多个位置使用这些对象。希望在多个地方使用模板是很常见的。
如果您为按钮定义了自定义外观,您可能希望将其应用于多个按钮,甚至应用程序中的所有按钮。XAML 资源系统提供了一种方法来执行此操作。您可以定义一个命名资源,然后在 XAML 中的其他地方使用它。
除了模板之外,对图形资源(例如画笔和形状)执行此操作也很常见。如果您的应用程序中使用了特定的配色方案,则可以将该方案的颜色和画笔定义为资源。
这是SolidColorBrush资源的简单应用程序。
<UserControl x:Class = "XAMLResources.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <UserControl.Resources> <SolidColorBrush x:Key = "brushResource" Color = "AliceBlue" /> </UserControl.Resources> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel> <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}" /> <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}"/> </StackPanel> </Grid> </UserControl>
在上面的XAML代码中,可以看到两个矩形都有StaticResource,brushResource的颜色是AliceBlue。
当上面的代码编译执行后,你会看到下面的输出。
应用程序.xaml
所有 Silverlight 应用程序都有一个名为App.xaml的文件。它包含应用程序范围的信息。例如,它有一个 Resources 属性,就像用户界面元素一样。
您在App.xaml文件中定义的资源可用于项目中的所有 XAML 文件。因此,与其将我的MainPage.xaml与这些类型的资源混在一起,不如将它们移到应用程序范围内。
<Application xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" x:Class = "XAMLResources.App" > <Application.Resources> <SolidColorBrush x:Key = "brushResource" Color = "AliceBlue" /> </Application.Resources> </Application>
应用类
与大多数 XAML 文件一样,App.xaml文件及其对应的代码隐藏文件定义了一个类。这个 Application 类是 Silverlight 应用程序的入口点。在App.xaml中通常涉及与应用范围的资源; 它的代码隐藏文件包含启动和关闭处理代码。
-
在创建 Application 类的实例后不久,Silverlight 引发其Application.Startup事件。
-
在这里我们创建用户界面。我们希望在启动事件中创建一个用户界面元素并将其分配给应用程序对象的 RootVisual 属性,这将成为 Silverlight 插件显示的用户界面。
public partial class App : Application { public App() { this.Startup += this.Application_Startup; this.Exit += this.Application_Exit; this.UnhandledException += this.Application_UnhandledException; InitializeComponent(); } private void Application_Startup(object sender, StartupEventArgs e) { this.RootVisual = new MainPage(); } private void Application_Exit(object sender, EventArgs e) {} private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (!System.Diagnostics.Debugger.IsAttached) { e.Handled = true; Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); }); } } private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e) { try { string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace; errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n"); System.Windows.Browser.HtmlPage.Window.Eval("throw new Error (\"Unhandled Error in Silverlight Application " + errorMsg + "\");"); } catch (Exception) {} } }
注意事项
请注意,您不能更改RootVisual。你必须只设置一次。如果您想在应用程序运行时更改用户界面,则必须通过更改MainPage的内容来实现,而不是尝试用不同的内容替换MainPage。
其他应用程序事件是Exit,这是您在用户界面即将消失时运行关闭代码的最后机会,以及UnhandledException,如果您的代码引发未处理的异常,则会引发该事件。
如果您没有为UnhandledException事件提供处理程序,或者如果该处理程序没有将事件标记为正在处理,UnhandledExceptions将有效地关闭您的 Silverlight 应用程序。
屏幕上的插件区域将变为空白,并向浏览器报告脚本错误。
Silverlight – 文件访问
在本章中,我们将看到 Silverlight 应用程序如何访问最终用户计算机上的文件。在 Silverlight 中有三种主要的方式来访问文件。选择取决于您需要使用文件的原因,以及您是否正在编写受信任的应用程序。
-
最灵活的选择是使用文件对话框类。通过打开和保存文件对话框,您可以访问最终用户选择的任何文件,只要该用户具有适当的权限。用户同意是这种方法的核心。用户必须选择要读取的文件,或者在保存时,他们选择要覆盖的文件或为您选择位置和文件名。
-
第二个选项是使用System.IO命名空间中的各种类。Silverlight 提供了诸如FileStream、StreamWriter、FileInfo、Directory和DirectoryInfo 之类的类,所有这些类都可以编写无需让用户参与即可打开和访问文件的代码。这对开发人员来说可能更方便,但当然,大多数用户不希望任何作为网页一部分下载的旧代码能够在他们的文件中搜索。
-
第三个选项是隔离存储,我们将在稍后讨论。
打开和保存文件对话框
保存文件对话框
所述SaveFileDialog类示出了标准的操作系统提供的用户界面,用于选择在哪里保存文件。
一些重要的功能是 –
-
为了使用它,我们创建了SaveFileDialog类的一个实例。
-
调用ShowDialog使其出现,返回码告诉我们用户是选择了保存文件的位置,还是取消了对话框。
-
您可能想知道那里与True的冗余比较。如果ShowDialog返回True值,则表示用户选择了一个文件。所以我们可以继续调用OpenFile方法,它返回一个Stream。
-
如果我们愿意,我们可以发现用户选择的名称。该对话框提供了一个名为SafeFileName的属性,但不包括路径。在任何情况下,写入数据的唯一方法是使用对话框返回的Stream。从开发人员的角度来看,这只是一个普通的.NET 流,因此我们可以将其包装在StreamWriter 中,以将文本写入其中。
打开文件对话框
OpenFileDialog 在使用上类似于SaveFileDialog。显然,您总是选择现有文件而不是新文件,但还有另一个重要区别。
-
它提供了一个名为MultiSelect的属性。如果将其设置为True,则用户可以选择多个文件。这意味着对话框需要稍微复杂的 API。
-
该SaveFileDialog只有一次在一个文件中的交易,但打开文件对话框能够更加适应,所以它不提供的OpenFile方法。我们需要扩展代码。根据对话框是处于单文件模式还是多选模式,您可以使用其File或Files属性。
-
在这里,在下面给出的示例中,我们处于单文件模式。因此,我们使用File,并在返回的FileInfo对象上调用OpenRead。
-
在多选模式下,我们将改用Files,它返回FileInfo对象的集合。
文件流
上面提到的第二种文件访问方法是直接使用FileStream类或System.IO命名空间中的相关类型。关于这一点没有太多可说的,因为在大多数情况下,它类似于使用完整的.NET Framework进行文件访问。
但是,有一些 Silverlight 特定的曲折。
-
首先,这种方法使您可以随时访问文件而无需用户干预,并且没有任何明显可见的文件活动迹象,只允许受信任的应用程序使用此技术。请记住,您需要用完浏览器才能获得更高的信任度。
-
第二个问题是只有某些特定文件夹中的文件可用。您只能读取和写入用户的文档、音乐、图片或视频文件下的文件。一个原因是 Silverlight 运行在多个平台上,并且例如 Apple Mac 的文件系统结构与 Windows 的文件系统结构非常不同。因此,跨平台文件访问必须在 Silverlight 支持的所有系统上可用的一组有限文件夹中工作。
-
由于这些文件夹将位于不同操作系统上的不同位置,并且它们的位置通常因用户而异,因此您需要使用Environment.GetFolderPath方法在运行时发现实际位置。
-
您可以检查起点下方的目录结构。System.IO命名空间中的Directory和DirectoryInfo类允许您枚举文件和目录。
考虑一个简单的示例,其中文件可以通过OpenFileDialog打开并通过SaveFileDialog将一些文本保存到文件中。
下面给出的是 XAML 代码,其中创建了两个按钮和一个文本框。
<UserControl x:Class = "FileDialogs.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition Height = "265*" /> </Grid.RowDefinitions> <Button x:Name = "saveFileButton" Content = "Save" Width = "75" FontSize = "20" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "12,12" Click = "saveFileButton_Click" /> <Button x:Name = "openFileButton" Content = "Open" Width = "75" FontSize = "20" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "101,12,0,0" Click = "openFileButton_Click" /> <TextBox x:Name = "contentTextBox" Grid.Row = "1" Margin = "12" FontSize = "20" /> </Grid> </UserControl>
下面给出了用于打开和保存文件的单击事件实现的 C# 代码。
using System; using System.Diagnostics; using System.IO; using System.Windows; using System.Windows.Controls; namespace FileDialogs { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void saveFileButton_Click(object sender, RoutedEventArgs e) { var save = new SaveFileDialog(); save.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"; save.DefaultExt = ".txt"; if (save.ShowDialog() == true) { Debug.WriteLine(save.SafeFileName); using (Stream saveStream = save.OpenFile()) using (var w = new StreamWriter(saveStream)) { var fs = saveStream as FileStream; if (fs != null) { w.Write(contentTextBox.Text); } } } } private void openFileButton_Click(object sender, RoutedEventArgs e) { var open = new OpenFileDialog(); if (open.ShowDialog() == true) { using (Stream openStream = open.File.OpenRead()) { using (var read = new StreamReader(openStream)) { contentTextBox.Text = read.ReadToEnd(); } } } } } }
当上面的代码编译执行后,你会看到下面的网页,里面有两个按钮。
单击打开按钮,这将打开OpenFileDialog以选择一个文本文件。
选择一个文本文件并单击Open,您将在文本框中看到文本。
要将文本保存到文件中,请更新文本。
单击“保存”按钮将更改保存到新文本文件或现有文件。
要保存对现有文本文件的更改,请在SaveFileDialog 中选择文本文件,但如果要保存对新文件的更改,请输入文件名并单击“保存”按钮。
Silverlight – 查看模型
在本章中,我们将研究 Silverlight 软件开发中的一项重要技术,即视图模型的使用。
-
该视图模型是一个关键的部分,其通过保持视图从模型中分离引入了一个称为分离呈现技术。
-
视图模型提供了一种实现分离呈现的方法,我们将看到它们如何利用 Silverlight 的数据绑定来减少用户界面中所需的代码量。
UI 开发挑战
视图模型旨在解决开发用户界面软件时经常出现的某些问题。也许最重要的一点是用户界面代码通常很难进行不可分割的测试,尤其是自动化单元测试。还有一些代码质量问题会影响代码的持续灵活性和可维护性。
-
如果您遵循 Visual Studio 的设计工具引导您走下去的阻力最小的道路,您最终可能会在后面的代码中放入太多代码。
-
看到大量应用程序功能被添加到后面的代码中是很常见的。
-
很少有开发人员会真正计划将业务逻辑放入用户界面类中,但因为这是 Visual Studio 放置事件处理程序的地方,所以它成为完成工作非常方便的地方。
-
人们普遍认为,如果类具有明确定义且合理范围窄的职责,则软件更易于开发和维护。
-
背后的代码的工作是在必要时直接与构成用户界面的对象进行交互。
-
一旦您开始放置决定您的应用程序如何运行的代码,这往往会导致问题。
-
不仅应用程序逻辑会流入应该与用户界面相关的代码,一些开发人员开始依赖控件和其他用户界面对象来保存重要的应用程序状态。
-
模型只保存数据,视图只保存格式化的日期,控制器(ViewModel)充当两者之间的联络人。控制器可能会从视图中获取输入并将其放置在模型上,反之亦然。
分离演示
为避免将应用程序逻辑置于代码后置或 XAML 中所导致的问题,最好使用一种称为分离呈现的技术。将 XAML 和代码隐藏在直接处理用户界面对象所需的最低限度之后,用户界面类还包含用于复杂交互行为、应用程序逻辑和其他所有内容的代码,如下图左侧所示。
分离演示的重要特征 –
-
通过分离呈现,用户界面类要简单得多。它当然有 XAML,但背后的代码做的很实用。
-
应用程序逻辑属于一个单独的类,通常称为模型。
-
许多开发人员尝试使用数据绑定将 XAML 中的元素直接连接到模型中的属性。
-
问题是模型完全关注应用程序做什么,而不是用户如何与应用程序交互。
-
大多数用户界面都有一些不属于应用程序模型的状态。例如,如果您的用户界面使用拖放,则需要跟踪一些内容,例如被拖动的项目现在在哪里,当它移过可能的放置目标时,它的外观应该如何变化,以及这些放置目标可能如何变化当项目拖过它们时发生变化。
-
这种状态会变得异常复杂,需要彻底测试。
-
在实践中,您通常希望一些其他类位于用户界面和模型之间。这有两个重要的作用。
-
首先,它使您的应用程序模型适应特定的用户界面视图。
-
其次,它是任何重要的交互逻辑存在的地方,我的意思是让您的用户界面按照您想要的方式运行所需的代码。
-
模型/视图/视图模型
View Model是分离呈现方法的一个例子,但让我们清楚我们在每一层中有什么样的东西。有三层 –
- 模型
- 看法
- 视图模型
模型
这是一个经典的对象模型,由与用户界面没有直接关系的普通 C# 类组成。
您通常希望您的模型代码能够在不引用任何用户界面库的情况下进行编译。事实上,您可能能够采用完全相同的源代码并将其编译成 Silverlight 应用程序、普通的 .NET 控制台应用程序,甚至服务器端 Web 代码。
模型中的类型应该代表您的应用程序使用的概念。
看法
视图通常是一个用户控件,它可能是您的 MainPage,也可能只是您页面的某个部分。
在大多数 Silverlight 应用程序中,最好将您的用户界面分成小块,为每个小块定义一个 UserControl 或 View。
Silverlight 应用程序在这方面并不是独一无二的。显然是 Silverlight 特有的东西是视图。你的用户界面越细粒度,事情就会越好。您不仅不太可能被其他开发人员在处理相同的文件时绊倒,而且保持小而简单自然会阻止导致意大利面条式代码的捷径。
例如,定义一个视图来表示列表中的单个项目是很常见的。
视图模型
最后,为每个View编写一个ViewModel。因此,这是ViewModel类的重要特性之一。
它的存在是为了服务于特定的视图。该视图模型是专门针对它出现在列表呈现的东西,如一个特定的数据项的特定方式。
这就是它被称为ViewModel 的原因;它特别适用于特定视图的底层模型。和 Model 一样,ViewModel也是一个普通的 C# 类。它不需要从任何特定类型派生。
碰巧的是,一些开发人员发现将一些常见功能放入基础 ViewModel 类中很方便,但该模式并不要求这样做。特别是,您的ViewModel不是从任何 Silverlight 特定类型派生的。但是,与模型不同的是,它可以在其属性中使用 Silverlight 类型。
例如,您的 ViewModel 可能选择使用户界面的某些部分仅在特定条件下可见,因此您可能提供 System.Windows.Visibility 类型的属性,这是 Silverlight 元素用于其 Visibility 属性的类型。这使得可以将元素(例如面板)的可见性直接绑定到 ViewModel。
例子
让我们看一个简单的例子,我们将在其中使用Model-View-ViewModel (MVVM)方法。
步骤 1 – 创建一个新的 Silverlight 应用程序项目SilverlightMVVMDemo。
Step 2 – 将三个文件夹(Model、ViewModel 和 Views)添加到您的项目中,如下所示。
第 3 步– 在 Model 文件夹中添加一个 StudentModel 类并将以下代码粘贴到该类中。
using System.ComponentModel; namespace SilverlightMVVMDemo.Model { public class StudentModel {} public class Student : INotifyPropertyChanged { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { if (firstName != value) { firstName = value; RaisePropertyChanged("FirstName"); RaisePropertyChanged("FullName"); } } } public string LastName { get { return lastName; } set { if (lastName != value) { lastName = value; RaisePropertyChanged("LastName"); RaisePropertyChanged("FullName"); } } } public string FullName { get { return firstName + " " + lastName; } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } } }
第 4 步– 将另一个 StudentViewModel 类添加到 ViewModel 文件夹中并粘贴以下代码。
using SilverlightMVVMDemo.Model; using System.Collections.ObjectModel; namespace SilverlightMVVMDemo.ViewModel { public class StudentViewModel { public ObservableCollection<Student> Students { get; set; } public void LoadStudents() { ObservableCollection<Student> students = new ObservableCollection<Student>(); students.Add(new Student { FirstName = "Mark", LastName = "Allain" }); students.Add(new Student { FirstName = "Allen", LastName = "Brown" }); students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" }); Students = students; } } }
步骤 5 –通过右键单击Views文件夹并选择Add New Item…添加Silverlight 用户控件。
步骤 6 – 单击添加。现在您将看到 XAML 文件。将以下代码添加到StudentView.xaml文件中,该文件包含不同的 UI 元素。
<UserControl x:Class = "SilverlightMVVMDemo.Views.StudentView" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel HorizontalAlignment = "Left"> <ItemsControl ItemsSource = "{Binding Path=Students}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation = "Horizontal"> <TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}" Width = "100" Margin = "3 5 3 5"/> <TextBox Text = "{Binding Path = LastName, Mode = TwoWay}" Width = "100" Margin = "0 5 3 5"/> <TextBlock Text = "{Binding Path = FullName, Mode=OneWay}" Margin = "0 5 3 5"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </Grid> </UserControl>
第 7 步– 现在将StudentView添加到MainPage.xaml文件中,如下所示。
<UserControl x:Class = "SilverlightMVVMDemo.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:views = "clr-namespace:SilverlightMVVMDemo.Views" mc:Ignorable = "d" d:DesignHeight = "576.316" d:DesignWidth = "863.158"> <Grid x:Name = "LayoutRoot" Background = "White"> <views:StudentView x:Name = "StudentViewControl" Loaded = "StudentViewControl_Loaded"/> </Grid> </UserControl>
第 8 步– 这是MainPage.xaml.cs文件中Loaded事件的实现,它将从ViewModel更新视图。
using System.Windows; using System.Windows.Controls; namespace SilverlightMVVMDemo { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } } private void StudentViewControl_Loaded(object sender, RoutedEventArgs e) { SilverlightMVVMDemo.ViewModel.StudentViewModel studentViewModelObject = new SilverlightMVVMDemo.ViewModel. StudentViewModel(); studentViewModelObject.LoadStudents(); StudentViewControl.DataContext = studentViewModelObject; } }
Step 9 – 编译并执行上述代码后,您将在网页上看到以下输出。
UI 与视图模型
MVVM 方法中最难的部分之一是确定分界线应该在哪里。哪些东西属于哪里并不总是很明显。
-
特别是,一些用户界面元素提供功能,根据严格的视图,这些功能应该属于 ViewModel。
-
一般来说,并不是所有在View中实现的行为都对ViewModel如此友好。
-
部分原因是没有任何标准方法可以打包 ViewModel 行为以供重用,尤其是在您想要使用设计环境(例如 Visual Studio 或 Blend)时。
MVVM 的优势
MVVM 提供以下优势 –
-
表示关注点的分离(视图、视图模型、模型)
-
干净的可测试和可管理的代码。可以在单元测试中包含表示层逻辑。
-
代码背后没有代码,因此表示层和逻辑是松散耦合的。
-
更好的数据绑定方式。
MVVM 的缺点
对于简单的 UI,MVVM 可能有点矫枉过正。当我们有复杂的数据绑定时,调试会有点困难。
Silverlight – 输入处理
在本章中,我们将学习如何在 Silverlight 应用程序中处理用户输入。Silverlight 提供了强大的 API,借助该 API,应用程序可以从各种设备(例如鼠标、键盘和触摸等)获取输入。
输入类型
有几种不同的方式,用户可以与您的应用程序进行交互。最明显的方法是使用鼠标。Silverlight 提供用于跟踪的事件 –
- 鼠标移动
- 按钮点击,以及
- 车轮活动
当然还有键盘,Silverlight 也支持触摸屏输入。如果您熟悉 Windows 中的触摸支持,您就会知道触摸输入可以表示为提供详细信息的低级事件,也可以概括为称为手势的高级事件。
鼠标事件
让我们先看看 Silverlight 提供的鼠标输入事件。一些事件与鼠标指针的移动有关。
-
该的MouseMove事件随时提出的指针同时移动到您已连接处理程序的元素。
-
您还可以获得MouseEnter和MouseLeave事件来通知您鼠标移入和移出元素的时间。
下面给出的是添加了椭圆和 TextBlock 的 XAML 代码。
<UserControl x:Class="MouseInput.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock x:Name = "mouseText" FontSize = "40" VerticalAlignment = "Top" Height = "76" Margin = "0,10,0,0" /> <Ellipse Name = "myEllipse" Width = "320" Height = "150" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "27,103,0,0" Stroke = "Black" StrokeThickness = "10" Fill = "#00FF0000" MouseEnter = "myEllipse_MouseEnter" MouseLeave = "myEllipse_MouseLeave" MouseMove = "myEllipse_MouseMove" /> </Grid> </UserControl>
下面给出了不同鼠标输入事件的实现。
using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace MouseInput { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void myEllipse_MouseEnter(object sender, MouseEventArgs e) { mouseText.Text = "Mouse Enter"; myEllipse.Stroke = new SolidColorBrush(Colors.Blue); } private void myEllipse_MouseLeave(object sender, MouseEventArgs e) { mouseText.Text = "Mouse Leave"; myEllipse.Stroke = new SolidColorBrush(Colors.Black); } private void myEllipse_MouseMove(object sender, MouseEventArgs e) { mouseText.Text = "Mouse Move: " + e.GetPosition(myEllipse); } } }
当上面的代码编译执行后,你会看到下面的输出。
当鼠标进入椭圆时,您将看到颜色和坐标的变化。
当鼠标离开椭圆时,它会显示一条消息“鼠标离开”,并将更改为默认颜色。
键盘
用户向您的应用程序输入文本数据的最简单方法是通过键盘(如果可用)。请记住,并非所有移动设备都有键盘,笔记本电脑和台式机除外。
-
Silverlight 为键盘输入提供了两个简单的事件KeyUp和KeyDown。
-
这两个都将KeyEventArgs传递给处理程序,并且 Key 属性指示按下了哪个键。
-
在下面的示例中,处理了一些键盘输入。
-
下面的示例定义了 Click 事件的处理程序和KeyDown事件的处理程序。
下面给出了 XAML 代码,其中添加了不同的 UI 元素。
<UserControl x:Class = "KeyboardInput.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <StackPanel Orientation = "Horizontal" KeyDown = "OnTextInputKeyDown"> <TextBox Width = "400" Height = "30" Margin = "10"/> <Button Click = "OnTextInputButtonClick" Content = "Open" Margin = "10" Width = "50" Height = "30"/> </StackPanel> </Grid> </UserControl>
下面给出了处理不同键盘和单击事件的 C# 代码。
using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace KeyboardInput { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void OnTextInputKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.O) { handle(); e.Handled = true; } } private void OnTextInputButtonClick(object sender, RoutedEventArgs e) { handle(); //e.Handled = true; } public void handle() { MessageBox.Show("Do you want to open a file?"); } } }
编译并执行上述代码后,您将看到以下内容 –
如果您单击“打开”按钮或单击文本框并单击“确定”,则会显示相同的消息。
我们建议您执行上述示例以更好地理解。
Silverlight – 独立存储
第三种文件访问机制是隔离存储机制,它提供与登录用户相关联的存储。API 通过.NET System.IO命名空间中的Stream类呈现数据。因此,与我们目前看到的其他机制一样,您可以使用System.IO 中的其他类型来处理流,从而使您能够存储文本或二进制数据。
一些重要的功能是 –
-
这种存储机制称为隔离存储,因为存储是分区的,并且 Silverlight 应用程序只能访问某些部分。
-
您无法访问任何旧的存储数据。首先,商店是按用户划分的。Silverlight 应用程序无法为与登录并运行应用程序的用户不同的用户访问商店。
-
这与您的 Web 应用程序可能使用的任何识别机制无关。这是需要记住的重要一点,因为一些共享计算机的人不会为单独的 Windows 帐户而烦恼,并且习惯于登录和退出他们使用的网站。
使用隔离存储
隔离存储并不是 Silverlight 独有的。该 API 最初是为Windows 窗体引入的,目的是使从 Web 启动的应用程序能够在部分信任的情况下在本地存储数据。实现是不同的,无法从 Silverlight访问完整的.NET Framework 独立存储,反之亦然。
但是,如果您使用过它,那么这里的步骤看起来会非常熟悉。
-
您首先询问用户特定的商店。在这种情况下,我们要求为应用程序提供一个。如果我们希望站点上所有 XAP 共享每个站点的存储,我们将调用GetUserStoreForSite。
-
这两种方法都返回一个IsolatedStorageFile对象,这是一个非常无用的名称,因为它代表一个目录,而不是一个文件。
-
要访问一个文件,你需要问IsolatedStorageFile的流。
-
我们使用IsolatedStorageFileStream类,它的构造函数要求您将IsolatedStorageFile对象作为参数传递。
-
所以我们正在商店中创建一个新文件。该文件在磁盘上的确切位置未知。
-
包含目录具有随机元素,以便无法猜测文件的名称。
-
如果没有这个,恶意网站可能会在用户的计算机上放置一个文件,然后构造一个文件 URL 来打开它,以期欺骗用户单击本地执行程序的链接。
-
Windows 中内置了各种其他保护措施,试图防止这种情况发生,但这是另一层防御措施,以防其他保护措施以某种方式被禁用或绕过。
-
该文件将存储在用户配置文件中的某个位置,但您对它的了解也就这么多。您的IndependentStorageFileStream不会报告其真实位置。
让我们看一个简单的例子,它跟踪应用程序运行了多少次。下面给出的是 XAML 代码。
<UserControl x:Class = "StoreRunCount.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock x:Name = "runCountText" FontSize = "20" /> </Grid> </UserControl>
这是使用隔离存储的 C# 代码。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; using System.IO; namespace StoreRunCount { public partial class MainPage : UserControl { const string RunCountFileName = "RunCount.bin"; public MainPage() { InitializeComponent(); int runCount = 0; using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { if (store.FileExists(RunCountFileName)) { using (var stm = store.OpenFile(RunCountFileName, FileMode.Open, FileAccess.Read)) using (var r = new BinaryReader(stm)) { runCount = r.ReadInt32(); } } runCount += 1; using (var stm = store.OpenFile(RunCountFileName, FileMode.Create, FileAccess.Write)) using (var w = new BinaryWriter(stm)) { w.Write(runCount); } } runCountText.Text = "You have run this application " + runCount.ToString() + " time(s)"; } } }
编译并执行上述代码后,您将看到以下网页,该网页将显示您运行此应用程序的次数。
增加配额
如果由于某种原因初始数量不足,应用程序可能会要求更多空间。不能保证请求会成功。Silverlight 将询问用户是否愿意为应用程序授予更多空间。
顺便说一下,您只能在响应用户输入(例如单击)时请求更多存储空间。如果您尝试在其他时间询问它,例如在插件加载时或在计时器处理程序中,Silverlight 将自动使请求失败,甚至不会提示用户。额外配额仅适用于用户与之交互的应用程序。
该IsolatedStorageFile对象提供了管理配额三名成员-
- 可用空间
- 增加配额
- 配额
可用空间
AvailableFreeSpace 属性告诉您有多少配额仍然可用。
请注意,即使是空子目录也会消耗一些配额,因为操作系统需要在磁盘上分配空间来表示目录。因此,可用空间可能小于总配额减去所有文件的总大小。
增加配额
如果您没有足够的空间来继续,您可以通过调用IncreaseQuotaTo方法来请求更多空间。
配额
在这里,我们使用第三个属性Quota来发现当前的配额大小,然后我们添加获得新请求的配额所需的额外数量。
该方法返回True或False以指示我们是否分配了我们要求的内容。请注意,Silverlight 可能决定分配比您要求的更多的空间。
这是一个简单的示例,用于在单击按钮时增加配额。下面给出的是 XAML 代码。
<UserControl x:Class = "ChangeQuota.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock x:Name = "infoText" FontSize = "20" TextWrapping = "Wrap" /> <Button x:Name = "increaseQuota" Content = "Increase" HorizontalAlignment = "Center" FontSize = "20" VerticalAlignment = "Center" Click = "increaseQuota_Click" /> </Grid> </UserControl>
这是增加配额的点击事件的实现。
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; namespace ChangeQuota { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void increaseQuota_Click(object sender, RoutedEventArgs e) { using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) { long newQuota = isoStore.Quota + 10240; if (isoStore.IncreaseQuotaTo(newQuota)) { infoText.Text = "Quota is " + isoStore.Quota + ", free space: " + isoStore.AvailableFreeSpace; } else { infoText.Text = "Meanie!"; } } } } }
当上面的代码编译执行后,你会看到下面的输出。
单击“增加”时,会出现提示。它要求将配额增加到比现有配额大 10KB。
当您单击Yes 时,它会打印出可用的配额数量。
我们建议您执行上述示例以更好地理解。
Silverlight – 文本
在本章中,我们将了解 Silverlight 提供的显示文本的功能。文本块用于所有文本渲染和 Silverlight。其他重要功能是 –
- 它可以用于简单的纯文本,也可以应用多种格式样式。
- Silverlight 支持一组标准的内置字体。
- 当您的应用程序视觉风格需要不那么普通的东西时,您还可以下载自定义字体。
文本块
为了显示文本,我们使用 Silverlight 教科书元素,这是一个用于显示少量只读文本的轻量级控件。事实上,我们已经看到了很多,因为它的基本用法并不需要太多解释。您只需设置 text 属性,它就会为您显示该文本。
<TextBlock Text = "Print Testing" HorizontalAlignment Center" FontFamily = "Georgia"/>
TextBlock 类的层次继承如下,
下面给出了TextBlock类的常用属性。
Sr. No. | 属性和描述 |
---|---|
1 |
ContentEnd 获取 TextBlock 中文本内容结尾的 TextPointer 对象。 |
2 |
ContentStart 获取 TextBlock 中文本内容开头的 TextPointer 对象。 |
3 |
IsTextSelectionEnabled 获取或设置一个值,该值指示是否通过用户操作或调用与选择相关的 API 在 TextBlock 中启用文本选择。 |
4 |
IsTextSelectionEnabledProperty 标识 IsTextSelectionEnabled 依赖项属性。 |
5 |
LineHeight 获取或设置每行内容的高度。 |
6 |
MaxLines 获取或设置 TextBlock 中显示的最大文本行数。 |
7 |
SelectedText 获取选定文本的文本范围。 |
8 |
SelectionEnd 获取 TextBlock 中所选文本的结束位置。 |
9 |
SelectionHighlightColor 获取或设置用于突出显示选定文本的画笔。 |
10 |
SelectionStart 获取 TextBlock 中所选文本的起始位置。 |
11 |
Text 获取或设置 TextBlock 的文本内容。 |
12 |
TextAlignment 获取或设置一个值,该值指示文本内容的水平对齐方式。 |
13 |
TextTrimming 获取或设置当内容溢出内容区域时要采用的文本修剪行为。 |
14 |
TextWrapping 获取或设置 TextBlock 如何包装文本。 |
下面给出了TextBlock类的常用事件。
Sr. No. | 事件和描述 |
---|---|
1 |
ContextMenuOpening 在系统处理显示上下文菜单的交互时发生。 |
2 |
SelectionChanged 当文本选择已更改时发生。 |
下面给出了TextBlock类中常用的方法。
Sr. No. | 方法和说明 |
---|---|
1 |
Focus 聚焦 TextBlock,就像它是传统的可聚焦控件一样。 |
2 |
Select 选择 TextBlock 中的文本范围。 |
3 |
SelectAll 选择 TextBlock 中的全部内容。 |
跑步
有时您希望对格式进行细粒度控制并为整个文本块设置一种样式。有时格式化单个单词甚至字母很有用,如果您想要这样,那么不要使用Text属性,而是将文本放在TextBlock 中作为内容。如果您使用的是代码,这对应于向TextBlock内联属性添加项目。
使用这种方法,您可以添加一系列运行元素。每个 Run 支持相同的字体系列、前端粗细、前景等用于控制文本样式的属性。尽管 Run 是一个单独的元素,但这不会中断流程。
让我们看一个简单的例子,它在TextBlock 中包含多个Run元素。下面给出的是 XAML 代码。
<UserControl x:Class = "SilverlightRunDemo.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock Width = "192" TextWrapping = "Wrap" FontFamily = "Verdana"> <Run Text = "Hello, " /> <Run FontWeight = "Bold" Text = "world!" /> <Run Text = "You" /> <Run FontStyle = "Italic" Text = " are " /> <Run Text = "learning" FontSize = "40" FontFamily = "01d English Text MT" /> <Run Text = " the " /> <Run Text = "basics of " Foreground = "Blue" /> <Run Text = " Silverlight." FontSize = "30" /> </TextBlock> </Grid> </UserControl>
当上面的代码编译执行后,你会看到下面的输出。
如您所见,此文本块通过使用Run元素以不同的格式样式排列。
顺便说一句,您不需要在运行中包装文本的每一位。您可以将文本块的大部分内容保留为纯文本,只需将run应用于需要不同格式的部分,如下所示。
<TextBlock> Hello, <Run FontWeight = "Bold" Text =" world!"/> </TextBlock>
越线
Silverlight 通常会忽略 XAML 中的换行符。它假定大多数空白都存在以使它们更易于阅读,因为您实际上希望该空白出现。
让我们看看这个 XAML 代码,其中包含三行单独的文本。
<TextBlock> This is not the end. It is not even the beginning of the end. But it is, perhaps, the end of the beginning </TextBlock>
当上面的代码编译执行后,你会看到下面的输出。
如您所见,它忽略了换行符并将所有文本一起执行。
-
如果您启用text wrapping,它将在需要使文本适合的位置放置换行符,但它会忽略示例中的换行符。
-
如果您只想添加显式换行符,则需要在文本块内添加换行符标记。后面的文本将在新行开始。
让我们通过添加LineBreak标记再次查看相同的示例。
<TextBlock FontSize = "16"> This is not the end. <LineBreak/> It is not even the beginning of the end. <LineBreak/> But it is, perhaps, the end of the beginning </TextBlock>
执行上述代码时,您将看到它现在看起来像 XAML 中指定的那样。
内置字体
Silverlight 有一组固定的内置字体系列。由于历史原因,这些字体实际上有不同的姓氏。默认系列在 Mac OS 和 Windows 上在技术上是不同的,例如在 Mac OS 上它是 Lucida Grande,而在 Windows 上它几乎相同但命名为 Lucida Sans Unicode。
下面给出了一些最常用的字体。
Fonts |
---|
Arial |
Arial Black |
Comic Sans MS |
Courier New |
Georgia |
Lucida Grande (Mac) or Lucida Sans Unicode (Windows) |
Times New Roman |
Trebuchet MS |
Verdana |
Silverlight – 动画
动画允许您创建真正动态的用户界面。它通常用于应用效果,例如,当您移过它们时会增长的图标、旋转的徽标、滚动到视图中的文本等。
有时,这些效果似乎过于浮华。如果使用得当,动画可以通过多种方式增强应用程序。它们可以使应用程序看起来更灵敏、更自然、更直观。
例如,当您单击时滑入的按钮感觉就像一个真实的物理按钮,而不仅仅是另一个灰色矩形。动画还可以将注意力吸引到重要元素上,并引导用户过渡到新内容。
Silverlight 的动画方法是声明性的,而不是专注于帧动画序列。
定义动画
动画通常在资源部分中定义。事实上,它们通常被包裹在一个故事板元素中,我们稍后会详细介绍。
-
它提供了一个 Begin() 方法,因此可以从代码中调用动画。
-
动画也可以放在控件模板中的视觉状态元素内。
声明式动画
Silverlight 中的动画是声明性的。他们描述了希望发生的事情。由 Silverlight 来解决如何实现这一目标。所以动画通常遵循我们告诉 Silverlight 我们想要改变的模式。
这始终是某些命名元素的某些属性,即TargetName和TargetProperty。
<DoubleAnimation Storyboard.TargetName = "myRectangle" Storyboard.TargetProperty = "Opacity" From = "0" To = "1" Duration = "0:0:5" />
-
我们说我们希望该属性如何改变,在这种情况下,我们将不透明度从零值更改为值 1。换句话说,我们喜欢目标元素从不透明渐变为透明。
-
最后,我们说我们希望这需要多长时间,在这种情况下需要五秒钟。
-
double 在这个 double 动画中的意义在于它的目标是一个 double 类型的属性,因此是一个浮点值。
-
如果要为表示颜色的属性设置动画,请改用颜色动画。
让我们看一个简单的双动画示例。下面给出的是 XAML 代码,其中添加了两个按钮、一个矩形和两个故事板。
<UserControl x:Class = "DoubleAnimationExample.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignWidth = "640" d:DesignHeight = "480"> <UserControl.Resources> <Storyboard x:Name = "fadeDown"> <DoubleAnimation Storyboard.TargetName = "myRectangle" Storyboard.TargetProperty = "Opacity" From = "1" To = "0" Duration = "0:0:5" /> </Storyboard> <Storyboard x:Name = "fadeUp"> <DoubleAnimation Storyboard.TargetName = "myRectangle" Storyboard.TargetProperty = "Opacity" From = "0" To = "1" Duration = "0:0:5" /> </Storyboard> </UserControl.Resources> <Grid x:Name = "LayoutRoot"> <Rectangle x:Name = "myRectangle" Fill = "Blue" Width = "300" Height = "100" HorizontalAlignment = "Center" VerticalAlignment = "Top" Margin = "0,30" /> <Button x:Name = "fadeUpButton" Content = "Up" Width = "80" Height = "30" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "50,140,0,0" Click = "fadeUpButton_Click" /> <Button x:Name = "fadeDownButton" Content = "Down" Width = "80" Height = "30" HorizontalAlignment = "Left" VerticalAlignment = "Top" Margin = "50,180,0,0" Click = "fadeDownButton_Click" /> </Grid> </UserControl>
这是 C# 中不同事件的实现。
using System.Windows; using System.Windows.Controls; namespace DoubleAnimationExample { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void fadeUpButton_Click(object sender, RoutedEventArgs e) { fadeUp.Begin(); } private void fadeDownButton_Click(object sender, RoutedEventArgs e) { fadeDown.Begin(); } } }
当上面的代码编译执行后,你会看到下面的输出。
重复和反转
动画提供了一些属性来自动重复和所有反向动画。
-
如果您将重复行为属性设置为时间垃圾邮件,动画将循环重复,直到指定的时间段过去,或者您可以告诉它您希望它重复多少次。
-
这支持小数点,因此您可以重复四次半。
-
您可以永远重复,也可以告诉动画一旦到达终点,它应该反向运行回到起点。
关键帧动画
通常从 A 到 B 的简单动画有点太简单了。例如,您想要制作一个从地面弹起的球的动画。这不是简单的点对点移动。球落下,逐渐加速,然后在击中底部时改变方向。当它回到其行程的顶部时再次放慢速度。
让我们看一个关键帧动画的简单例子。
下面给出的是 XAML 代码,其中包含一个椭圆和带关键帧的双动画。
<UserControl x:Class = "LinearKeyFrames.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" Width = "400" Height = "300"> <UserControl.Resources> <Storyboard x:Name = "ballAnim" SpeedRatio = "0.2"> <DoubleAnimation From = "0" Duration = "00:00:03" To = "96" Storyboard.TargetName = "ellipse" Storyboard.TargetProperty = "(Canvas.Left)" /> <DoubleAnimationUsingKeyFrames Storyboard.TargetName = "ellipse" Storyboard.TargetProperty = "(Canvas.Top)"> <LinearDoubleKeyFrame KeyTime = "00:00:00" Value = "0"/> <LinearDoubleKeyFrame KeyTime = "00:00:00.5" Value = "16" /> <LinearDoubleKeyFrame KeyTime = "00:00:01" Value = "48"/> <LinearDoubleKeyFrame KeyTime = "00:00:01.5" Value = "112"/> <LinearDoubleKeyFrame KeyTime = "00:00:02" Value = "48"/> <LinearDoubleKeyFrame KeyTime = "00:00:02.5" Value = "16"/> <LinearDoubleKeyFrame KeyTime = "00:00:03" Value = "0"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </UserControl.Resources> <Grid x:Name = "LayoutRoot" Background = "White"> <Canvas> <Ellipse x:Name = "ellipse" Fill = "Aqua" Width = "50" Height = "50" /> </Canvas> </Grid> </UserControl>
这是鼠标左键按下事件的实现,当用户在网页上按下鼠标左键时,该事件将开始动画。
using System.Windows.Controls; using System.Windows.Input; namespace LinearKeyFrames { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this.MouseLeftButtonDown += new MouseButtonEventHandler(Page_MouseLeftButtonDown); } void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { ballAnim.Begin(); } } }
当上面的代码编译执行后,你会看到下面的输出。
当您单击网页时,您将看到球开始移动。
Silverlight – 视频和音频
在本章中,我们将看到 Silverlight 设施如何播放视频和音频。该MediaElement的是在Silverlight中所有的视频和音频的心脏。这允许您在应用程序中集成音频和视频。该MediaElement的类工程等为类似的方式形象类。您只需将其指向媒体,它就会呈现音频和视频。
主要区别在于它将是一个移动图像,但如果您将其指向仅包含音频而没有视频的文件(例如 MP3),它将播放该文件而不在屏幕上显示任何内容。
MediaElement 作为 UI 元素
MediaElement派生自框架元素,它是所有 Silverlight 用户界面元素的基类。这意味着它提供了所有标准属性,因此您可以修改其不透明度、设置剪辑或转换它等等。
让我们看一个MediaElement的简单示例。
打开 Microsoft Blend for Visual Studio 并创建一个新的 Silverlight 应用程序项目。
现在将视频或音频文件拖入 Blend 设计界面。
它将向表面添加一个 MediaElement,并在您的项目中添加视频文件的副本。您可以在解决方案资源管理器中看到它。
你可以移动它,改变它的大小,你可以做一些事情,比如应用旋转等。
现在,它将在MainPage.xaml文件中为您生成相关的 XAML,如下所示。
<UserControl x:Class = "MediaElementDemo.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <MediaElement x:Name = "Microsoft_Silverlight_DEMO_mp4" Margin = "51,49,53,53" Source = "/Microsoft Silverlight DEMO.mp4" Stretch = "Fill" RenderTransformOrigin = "0.5,0.5"> <MediaElement.RenderTransform> <CompositeTransform Rotation = "-18.384"/> </MediaElement.RenderTransform> </MediaElement> </Grid> </UserControl>
当上述应用程序编译并执行后,您将看到该视频正在您的网页上播放。
控制
该MediaElement的只是呈现的媒体。它不提供任何标准的播放器控件。它会自动开始播放并在播放结束时停止,用户无法暂停或以其他方式控制它。所以在实践中,大多数应用程序都希望为用户提供更多的控制权。
您可以通过将AutoPlay设置为False来禁用自动播放。这意味着媒体播放器在您询问之前不会播放任何内容。
<MediaElement x:Name = "Microsoft_Silverlight_DEMO_mp4" AutoPlay = "False" Margin = "51,49,53,53" Source = "/Microsoft Silverlight DEMO.mp4" Stretch = "Fill" RenderTransformOrigin = "0.5,0.5">
因此,当您想播放视频时,只需调用MediaElement Play() 方法即可。它还提供停止和暂停方法。
让我们再次看一下同一个例子,并稍微修改一下以允许一点控制。在MediaElement 中附加MouseLeftButtonDown处理程序,如下面的 XAML 代码所示。
<UserControl x:Class = "MediaElementDemo.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <MediaElement x:Name = "Microsoft_Silverlight_DEMO_mp4" AutoPlay = "False" MouseLeftButtonDown = "Microsoft_Silverlight_DEMO_mp4_MouseLeftButtonDown" Margin = "51,49,53,53" Source = "/Microsoft Silverlight DEMO.mp4" Stretch = "Fill" RenderTransformOrigin = "0.5,0.5"> </MediaElement> </Grid> </UserControl>
这是MouseLeftButtonDown事件处理程序的实现,其中它将检查媒体元素的当前状态是否正在播放,然后它将暂停视频,否则将开始播放视频。
using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace MediaElementDemo { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void Microsoft_Silverlight_DEMO_mp4_MouseLeftButtonDown (object sender, MouseButtonEventArgs e) { if (Microsoft_Silverlight_DEMO_mp4.CurrentState == MediaElementState.Playing) { Microsoft_Silverlight_DEMO_mp4.Pause(); } else { Microsoft_Silverlight_DEMO_mp4.Play(); } } } }
当上面的代码编译执行时,你会看到空白的网页,因为我们已经将AutoPlay属性设置为False。当您单击网页时,它将启动视频。
当您再次单击该网页时,它将暂停视频。
Silverlight – 印刷
对于某些类型的应用程序来说,打印是一项重要的功能。在本章中,我们将了解 Silverlight 中的相关设施。
-
打印 API,以及所有 Silverlight 应用程序要打印时必须执行的基本步骤。用于选择水印的各种选项。
-
最简单的方法是打印屏幕上已有的用户界面元素的副本。
-
大多数应用程序都希望获得比这更先进的内容,并生成专门适用于打印的内容,并且在某些情况下,需要将内容拆分到多个页面上。
打印步骤
无论您是打印快照或屏幕上已有的内容,还是要进行完全自定义的多页打印输出,都需要相同的基本步骤。
-
打印 API 的核心是 PrintDocument 类。
-
您首先构建其中之一,当您调用它的 Print 方法时,它会显示用于启动打印作业的标准用户界面。
-
用户可以像往常一样选择打印机并配置设置。如果用户随后决定通过单击Print 继续,则PrintDocument将立即引发其PrintPage事件,并且该事件的处理程序提供要打印的内容。
-
为此,事件参数提供了一个PageVisual属性。
-
您可以将其设置为任何 Silverlight 用户界面元素,可以是屏幕上已经可见的元素,也可以是您专门为打印而创建的新元素。
打印现有元素
元素 最简单的选择是打印 Silverlight 应用程序屏幕上已有的内容。由于PrintPage事件参数PageVisual接受任何用户界面元素,因此您可以选择用户界面中的任何内容并打印它。
-
这只是使用 PrintScreen 键抓取屏幕截图的一小步。它比这略好一些,因为用户不必手动将屏幕截图粘贴到其他程序中以对其进行裁剪和打印。这仍然只是轻微的改进。
-
打印已经在屏幕上的内容是有问题的。
-
首先,不能保证在屏幕上工作的布局对纸张也能很好地工作。
让我们看一个简单的示例,其中ScrollViewer包含一些 UI 元素及其适合屏幕的布局。它根据浏览器窗口大小调整大小,并提供滚动条以确保即使不合适也可以访问所有内容。
下面给出的是 XAML 代码。
<UserControl xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sdk = "http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class = "SilverlightPrinting.MainPage" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "500"> <Grid x:Name = "LayoutRoot" Background = "White"> <Button x:Name = "print" Content = "Print" Click = "print_Click" Width = "60" Height = "20" Margin = "10,10,430,270"/> <ScrollViewer x:Name = "myScrollViewer" HorizontalScrollBarVisibility = "Auto" VerticalScrollBarVisibility = "Auto" Width = "400" Margin = "90,0,10,0"> <StackPanel> <Rectangle Fill = "Gray" Width = "100" Height = "100" /> <Button x:Name = "button" Content = "Button" Width = "75"/> <sdk:Calendar Height = "169" Width = "230"/> <Rectangle Fill = "AliceBlue" Width = "475" Height = "100" /> </StackPanel> </ScrollViewer> </Grid> </UserControl>
这是打印按钮单击事件的实现,它将打印ScrollViewer及其可见数据。
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Printing; namespace SilverlightPrinting { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void print_Click(object sender, RoutedEventArgs e) { PrintDocument pd = new PrintDocument(); pd.PrintPage += new System.EventHandler<PrintPageEventArgs>(pd_PrintPage); pd.Print("Print Screen Content"); } private void pd_PrintPage(object sender, PrintPageEventArgs e) { e.PageVisual = myScrollViewer; } } }
-
如您所见,在创建PrintDocument对象的Print 按钮单击事件中,我们将处理程序附加到其 PrintPage 事件。
-
您可以将PageVisual属性设置为引用ScrollViewer。
-
然后调用Print 方法。这需要一个字符串,它将在打印队列中显示为作业名称。
当上面的代码编译执行后,你会看到下面的输出。
当您单击“打印”按钮时,您将看到标准的“打印”对话框。
现在,选择默认打印机。出于演示的目的,让我们选择OneNote并单击打印按钮。您将看到ScrollViewer已打印。
请注意,滚动条在ScrollViewer上仍然可见。
自定义 UI 树
与打印屏幕上已经存在的内容不同,构建专门用于打印的用户界面元素树通常更有意义。这样,您可以确保仅在纸张上使用非交互式元素,并且可以创建更适合纸张形状和尺寸的专门布局。您可以创建一个仅用于打印的 UserControl。
让我们通过创建一个 Silverlight 项目并添加一个名为PrintLayout的UserControl 来看看一个简单的示例。
将设计时的宽度和高度设置为近似纸形。下面给出的是PrintLayout.xaml文件的 XAML 代码。
<UserControl x:Class = "PrintCustomUI.PrintLayout" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "768" d:DesignWidth = "960"> <Grid x:Name = "LayoutRoot" Background = "White"> <Grid.RowDefinitions> <RowDefinition Height = "Auto" /> <RowDefinition /> <RowDefinition Height = "Auto" /> </Grid.RowDefinitions> <TextBlock Text = "Silverlight" HorizontalAlignment = "Center" FontSize = "60" FontWeight = "Bold" FontFamily = "Georgia" /> <TextBlock Grid.Row = "2" Text = "Print Testing" HorizontalAlignment = "Center" FontFamily = "Georgia" FontSize = "24" Margin = "0,10"/> <Rectangle Grid.Row = "2" Height = "1" Fill = "Black" VerticalAlignment = "Top"/> <Ellipse Grid.Row = "1" Stroke = "Black" StrokeThickness = "10" Margin = "10"> <Ellipse.Fill> <RadialGradientBrush GradientOrigin = "0.2,0.2" Center = "0.4,0.4"> <GradientStop Color = "Aqua" Offset = "0.006" /> <GradientStop Color = "AntiqueWhite" Offset = "1" /> </RadialGradientBrush> </Ellipse.Fill> </Ellipse> </Grid> </UserControl>
下面给出的是MainPage.xaml文件中的代码,其中仅包含一个打印按钮。
<UserControl x:Class = "PrintCustomUI.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <Button Content = "Print..." Height = "23" HorizontalAlignment = "Left" Margin = "12,28,0,0" Name = "printButton" VerticalAlignment = "Top" Width = "75" Click = "printButton_Click" /> </Grid> </UserControl>
这是打印按钮的Click 事件实现。
using System; using System.Collections.Generic; using System; using System.Windows; using System.Windows.Controls; using System.Windows.Printing; namespace PrintCustomUI { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void printButton_Click(object sender, RoutedEventArgs e) { PrintDocument pd = new PrintDocument(); pd.PrintPage += new EventHandler<PrintPageEventArgs>(pd_PrintPage); pd.Print("Custom"); } void pd_PrintPage(object sender, PrintPageEventArgs e) { var pl = new PrintLayout(); pl.Width = e.PrintableArea.Width; pl.Height = e.PrintableArea.Height; e.PageVisual = pl; } } }
上述代码编译执行后,会在网页上看到如下输出。
单击打印并选择OneNote以打印布局。您将看到布局已打印。
可以看到它已经填满了可用空间。我们建议您执行上述示例以更好地理解。