在上一篇中讲述了如何安装适合自己需要的VS2010
以及相关帮助文档,由于在VS2010
中帮助文档的查询方式不同于以往的VS
,在上篇中还介绍了H3Viewer
这个软件,它是一个免费的软件,安装它之后可以在安装了VS2010
帮助文档之后以类似于以前查看MSDN
的方式查看帮助文档。除此之外,在上一篇还比较了几种常见的RIA
技术,比如Java Applet
、Flash
及Silverlight
,以及它们与普通Windows
应用程序在运行机制上的区别和限制。在这一篇开始涉及到Silverlight
了,这一篇主要是讲Silverlight
的开发工具VS2010
以及XAML
语言等知识。
创建Silverlight
项目
当我们创建一个Silverlight
项目时会提示是否创建一个承载项目,如下图所示:
由于在VS2010
中已经直接支持创建ASP.NET MVC2
的Web
项目,所以承载Silverlight
的Web
项目类型有三种:ASP.NET Web
应用程序项目、ASP.NET
网站及ASP.NET MVC Web
应用程序项目。ASP.NET Web
应用程序项目可以提供与Visual Studio .NET 2003 Web
项目相同的 Web
项目语义,它的编译模型与 Visual Studio .NET 2003
编译模型类似。项目中的所有代码文件(独立文件、代码隐藏文件以及类文件)将被编译成单个程序集并存储在 Bin
目录中。由于编译会创建单个程序集,因此可以指定程序集名称和版本等属性。如果我们仅仅是开发Silverlight
的话,这个可以随便选择一种类型,以便能在网页中查看Silverlight
的运行效果。
VS2010
界面
创建Silverlight
项目成功之后可以看到如下的界面:
在VS2010
中可以直接从工具箱中向Silverlight
界面中拖控件。在开发ASP.NET
时一个页面会分为两部分.aspx.cs
和.cs
,前者包含了设计代码,后者则是包含业务逻辑代码,和ASP.NET
开发一样,Silverlight
的项目中每个控件或者页面也是分为.xaml
和.xaml.cs
,.xaml
代码也是包含设计代码,.xaml.cs
则是包含业务逻辑代码。在每个Silverlight
项目中默认会有一个app.xaml
文件,这个文件有点类似于WinForm
项目中的program.cs
类,包含了项目启动时的设置,在创建一个Silverlight
项目成功后app.xam.cs
的代码如下:
- 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;
- namespace SilverlightDemo1
- {
- 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)
- {
- // 如果应用程序是在调试器外运行的,则使用浏览器的
- // 异常机制报告该异常。在 IE 上,将在状态栏中用一个
- // 黄色警报图标来显示该异常,而 Firefox 则会显示一个脚本错误。
- 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)
- {
- }
- }
- }
- }
可以在Application_Startup()
方法中通过设置RootVisual
属性来指定启动那个页面作为Silverlight
的启动界面。
关于XAML
在Silverlight
中使用XAML
作为Silverlight
的界面设计语言,XAML
是一种特殊的XML
格式(就像XHTML
也是一种特殊的XML
格式一样),现在我们不用太关注它,经过以后的练习就会慢慢理解XAML
语言的特点。下面是一个普通的XAML
页面代码:
对于普通的Silverlight
控件或者页面(也就是除app.xaml
),这个xaml
代码主要包含了几部分:它对应的后台代码的类名(在上图所示的是SilverlightDemo1.MainPage
);用户控件的高度和宽度(在上图中所示的高宽分别是300
和400
像素);顶级布局所使用的容器(在上图中使用的是Grid
)。在Silverlight
中定义了一个Panel
类,这个类是一个抽象类,它是用来界面布局的,Panel
类有如下子类:System.Windows.Controls.Canvas
、System.Windows.Controls.DockPanel
、System.Windows.Controls.Grid
、System.Windows.Controls.Primitives.TabPanel
、System.Windows.Controls.Primitives.ToolBarOverflowPanel
、System.Windows.Controls.Primitives.UniformGrid
、System.Windows.Controls.StackPanel
及System.Windows.Controls.VirtualizingPanel
和System.Windows.Controls.WrapPanel
。在WinForm
中我们直接往界面中拖控件就可以了,因为在WinForm
中我们使用X
和Y
坐标来定位控件的左上角顶点的位置,在ASP.NET
中则可以使用Table
或者DIV
来布局,在Silverlight
中界面布局和ASP.NET
及WinForm
中都不一样,相对要稍微复杂一些(个人感觉倒是有些和Java SE
类似,在Java SE
中有FlowLayout
、BorderLayout
、CardLayout
及GridLayout
),在Silverlight
中界面布局则有上面提到的那些类(莫非和Java SE
一样,因为要跨平台,所以才会复杂一些)。利用这些界面布局类及它们的组合可以实现复杂的界面布局,当然如果你觉得仍不能满足要求的话,可以界面布局类。关于这些布局类的用法将在下一篇讲解。
Silverlight
项目的编译
大家都知道.NET
项目都可以使用csc.exe
编译,其实VS
在编译项目是也是调用了csc.exe
的,所以对于平常的简单的想法的代码测试周公都是用记事本写代码然后在命令行下调用csc.exe
编译。用VS
编译项目最终也会调用csc.exe
来编译,和以前编译.NET
项目不同的是,编译Silverlight
项目多加了一个命令行参数,这个命令行参数是“nostdlib
”,它的作用说明如下:
从上图可以看出,使用“nostdlib
”参数的作用是不引用标准库。在.NET
类库中核心类库是mscorlib.dll
,使用这个参数的作用就是不引用mscorlib.dll
这些类(因为Silverlight
要跨操作系统要支持多浏览器,所以不能带有Windows
系统的特色)。尽管在Silverlight
中可以使用C#
或者VB.NET
编程,但是Silverlight
中所使用的是.NET
类库的子集,在某些用法上受到限制。甚至有些类或者有些方法出现在Silverlight
的运行环境中,但是这些类和这些方法并不能为开发者所用,所幸的是为了不必要的麻烦在编写代码时出现的智能感知中不会出现这些类或者这些方法。
当我们编译Silverlight
项目成功之后会得到一个dll
文件,它的文件结构如下:
也就是除了一个dll
文件之外还会生成如下文件:
一个.pdb
文件。假设Silverlight
项目名为SilverlightDemo1
,那个pdb
文件名为SilverlightDemo1.pdb
,这个文件包含了VS
需要的调试信息。
一个名为AppManifest.xaml
的文件。不管Silverlight
项目名是什么,这个文件名总不会变,在这个文件里包含了当前Silverlight
项目所需要的程序集。在本实例中AppManifest.xaml
的内容如下所示:
一个测试用的html
文件。假设Silverlight
项目名为SilverlightDemo1
,那个html
文件名为SilverlightDemo1TestPage.html
,即{Silverlight
项目名}TestPage.html
,也就是会以Silverlight
项目名加TestPage
作为文件名的html
文件。这个文件文件演示了如何在页面中嵌入Silverlight
控件,它的代码如下:
- <!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>SilverlightDemo1</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">
- 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 = "应用程序中未处理的错误" + appSource + "\n" ;
- errMsg += "代码: "+ iErrorCode + " \n";
- errMsg += "类别: " + errorType + " \n";
- errMsg += "消息: " + args.ErrorMessage + " \n";
- if (errorType == "ParserError") {
- errMsg += "文件: " + args.xamlFile + " \n";
- errMsg += "行: " + args.lineNumber + " \n";
- errMsg += "位置: " + args.charPosition + " \n";
- }
- else if (errorType == "RuntimeError") {
- if (args.lineNumber != 0) {
- errMsg += "行: " + args.lineNumber + " \n";
- errMsg += "位置: " + args.charPosition + " \n";
- }
- errMsg += "方法名称: " + 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/x-silverlight-2" width="100%" height="100%">
- <param name="source" value="SilverlightDemo1.xap"/>
- <param name="onError" value="onSilverlightError" />
- <param name="background" value="white" />
- <param name="minRuntimeVersion" value="3.0.40818.0" />
- <param name="autoUpgrade" value="true" />
- <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0" style="text-decoration:none">
- <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="获取 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>
从代码中可以看到,如果浏览此页面的客户端没有安装Silverlight
客户端的话,就会看到一个下载安装Silverlight
客户端的提示,用户点击链接就可以跳转到微软官方网站下载Siverlight
。下载完成会提示用户是否安装。也就是在下载和安装Silverlight
时都会得到明确的提示,用户可以明确地选择是否下载或安装,这一点很值得国内的公司学习。国内很多以“正当”、“安全”自居的公司提供的软件总是模糊、混淆某些概念来达到自己不可告人的目的,甚至还有几款装机量上亿的软件经常扫描用户的非系统盘之外的敏感区域,这些公司都应该好好学习一下国外软件的做法。
一些dll
文件。这些dll
文件是运行当前Silverlight
项目所需要的依赖文件。在AppManifest.xaml
文件中我们看到了里面有除SilverlightDemo1.dll
之外的如下文件:
System.ComponentModel.DataAnnotations.dll
System.Windows.Controls.Data.dll
System.Windows.Controls.Data.Input.dll
System.Windows.Controls.dll
System.Windows.Controls.Navigation.dll
System.Windows.Data.dll
zh-Hans/System.ComponentModel.DataAnnotations.resources.dll
zh-Hans/System.Windows.Controls.resources.dll
zh-Hans/System.Windows.Controls.Data.resources.dll
zh-Hans/System.Windows.Controls.Data.Input.resources.dll
zh-Hans/System.Windows.Controls.Navigation.resources.dll
zh-Hans/System.Windows.Data.resources.dll
在上面的文件都是运行Siverlight
项目的依赖文件。其中zh-Hans
文件夹中的文件都是一些资源文件,当然除了zh-Hans
之中的文件之外,还有其它类似于zh-Hans
文件夹的文件夹,它们里面的文件文件名和zh-Hans
文件夹下的文件名一样,这些文件是语言资源文件。
说到Silverlight
项目的依赖文件就不得不说一下Silverlight
项目的核心文件。大家知道Siverlight
程序是被下载到客户端执行的,所以需要在客户端安装Silverlight
运行环境,为了方便在不同网络环境下的用户下载和安装Silverlight
运行环境,所以这个运行环境要尽可能的精简(实际上只有5M
),既然它被精简了所以自然不可能提供.NET Framework
提供的所有功能。在Silverlight
运行环境中包含了如下程序集:
mscorlib.dll
:注意此mscorlib.dll
非.NET Framework
中的mscorlib.dll
,不过在Silverlight
运行环境中它提供了类似于NET Framework
中的mscorlib.dll
的功能,是Silverlight
运行环境中核心类库(核心中的核心)。
System.dll
:提供了泛型、URI
处理及正则表达式相关功能的类。
System.Core.dll
:提供了对LINQ
的支持。
System.Net.dll
:提供了网络功能,这样我们下载Web
文件和创建基于Socket
的网络连接。
System.Window.dll
:提供在Silverlight
中创建UI
的类。
System.Window.Browser.dll
:提供了对HTML
元素交互操作的类。
System.Xml.dll
:提供了XmlReader
和XmlWriter
两个类用以处理Xml
。
可以看出在AppManifest.xaml
中出现的那些除SilverlightDemo1.dll
之外的dll
都没有在Silverlight
运行环境所提供的核心类库中。前面说了Siverlight
运行环境的设计理念是尽可能使其安装和下载体积小,所以Siverlight
运行环境的设计者在核心类库之外又提供了一些类,这些类提供的功能并不是在每个Silverlight
应用中都会用到(如果总会用到就会放到核心类库中了),所以以附加类库的形式提供。当利用VS
编译Silverlight
项目的时候,VS
会自动检测那些本项目需要但又不在Silverlight
核心类库中的dll
,所以我们会在bin
目录下会看到一些“不知道怎么跑出来的”dll
文件。
在这些附加类库中经常会用到的dll
有如下几个:System.Window.Controls.dll
、System.Window.Controls.Data.dll
、System.Window.Controls.Data.Input.dll
、System.Window.Controls.Input.dll
及System.Windows.Controls.Navigation.dll
,确实这几个文件都在我们的AppManifest.xaml
文件中出现了。
一个.xap
文件。同样假设Silverlight
项目名为SilverlightDemo1
,那个xap
文件名为SilverlightDemo1.xap
,这个xap
文件其实是一个压缩文件,我们可以直接使用WinRAR
或者其它压缩软件打开这个xap
文件(如果不嫌麻烦可以将SilverlightDemo1.xap
改名为SilverlightDemo1.xap.zip
再用解压软件打开)。下图是使用WinRAR
直接打开SilverlightDemo1.xap
的情景:
从上图中我们看到了前面提到的AppManifest.xaml
和SilverlightDemo1.dll
文件以及上面提高的“一些”dll
文件,这些dll
文件都是在AppManifest.xaml
中出现过的、SilverlightDemo1
项目所需的附加dll
。适用xap
的方式发布Silverlight
有两个好处:一是xap
文件是压缩过的文件,可以减少网络流量以提高下载速度;二是便于部署,如果你想部署Silverlight
部署到别某个网站仅仅需要将这个xap
文件拷贝到网站所在的目录然后创建一个嵌入Silverlight
的页面就够了,超级简单。
Silverlight
项目的部署
前面讲到部署Silverlight
项目需要的仅仅是一个xap
文件和一个包含了如何设置Silverlight
项目的网页文件。有时候出现这样的情况,创建项目的时候取了一个名字,到最后发布的时候觉得这个名字不直观,那么我们可以通过VS
来设置最终生成的Silverlight
项目的文件名,具体方法就是在Silverlight
项目上点击鼠标右键选择“属性”,出现如下窗口:
从上图可以看出,在这个面板中我们可以指定如下跟Silverlight
项目有关的东西:
应用程序集名称:即最终生成的dll
文件名;
默认空间名:即创建代码文件时默认所使用的namespace
名称;
启动对象名:可以看出为什么在App.xaml
中的Application_Startup()
方法中指定启动那个窗体就会启动那个窗体,因为默认是启动App
对象的,所以它的制定才有用,如果在项目中创建了多个类似于App.xaml
的文件,则会在这里出现多个选择;
生成的Silverlight
应用的版本:如果安装了多个Silverlight SDK
的话,这里会有多种选择;
最终生成xap
文件名:可以将其改为更直观的名字。
从本篇前面的讲解可以知道Silverlight
最终会被下载到客户端运行,客户端下载到的是一个xap
文件,这个xap
文件从本质上来说其实就是一个压缩文件。如果解压这个文件就可以得到Silverlight
项目的dll
文件,遇上有心人是可以利用一些反编译工具得到源代码的,如下图就是使用著名的反编译软件Reflector
打开本篇中的dll
文件的情形:
从图中可以看到利用这个软件可以很方便地查看没有经过任何处理的.NET
程序集或者Silverlight
程序集代码(以MSIL
形式存储的),所以为了安全起见不要再Silverlight
中保存任何隐私的、安全相关的数据。除此之外还可以对生成的程序集进行进行加密或者混淆,加密就是利用MSIL
指令的一些特点使反编译工具无法反编译出源代码,混淆时是对程序集中的变量名和方法名加以变化,使其不再具有望文知义的特点从而达到了即使反编译得到了源代码也难以阅读的目的。在VS
中本身就提供了一个代码混淆工具Dotfuscator
的社区版,这是一个免费但功能有限的.NET
代码混淆工具,它的界面如下:
如果是一般的项目,可以使用Dotfuscator
进行混淆,这样可以使一般的窥探者望而生畏。
对于软件的代码保护是一个长期以来一直在探讨的话题,在本篇里提出来只是让大家有这方面的意识,而不是让大家把大部分精力都放在如何组织窥探自己的源代码上了。对软件源代码的反保护和保护一直是矛和盾的问题,二者相互竞争相互发展,不管使用什么语言都难以彻底有效地避免这个问题。
总结
在本篇讲解了在VS
中开发Silverlight
的界面、Silverlight
项目的组成以及编译和部署Silverlight
项目时涉及到的一些知识和注意事项。本篇仍是在做准备,下一篇就会讲到Silverlight
的界面布局,学习开发Silverlight
面临的第一个问题就是界面布局问题,下一篇就会讲解常见的界面布局。
本文转自周金桥51CTO博客,原文链接:
http://blog.51cto.com/zhoufoxcn/391313
,如需转载请自行联系原作者