我们来开始我们的Digg应用的开发,先选择Visual Studio 2008 中的文件->新项目菜单项,使用新项目对话框创建一个“Silverlight Application” (注:你需要在Beta1发布后,下载和安装 VS 2008的Silverlight工具才能得到这个支持):
我们将该项目命名为“DiggSample”。在点击OK按钮后, Visual Studio 会显示另外一个对话框,允许我们选择我们是否只要创建一个Silverlight应用项目,或者还要加一个服务器端的ASP.NET Web项目到包含Silverlight应用的解决方案里去:
在这个例程里,我们将选择还要添加一个ASP.NET Web Application 项目到解决方案里去,并将它命名为“DiggSample_WebServer”。在点击OK之后,Visual Studio 会为我们创建一个解决方案,里面包含一个Silverlight 客户端应用和一个ASP.NET web 服务器端应用:
如果我们做一次编译的话, Visual Studio 会自动把编译好的 Silverlight 应用拷贝到我们的web服务器项目中去,不需要手工的步骤或配置。VS为我们创建的默认的web服务器项目包含一个ASP.NET网页和一个静态的 HTML网页,我们可以用来运行和测试其中的Silverlight应用。
理解Silverlight应用里都有些什么
在默认情形下,一个新建的Silverlight应用项目包含一个Page.xaml和一个 App.xaml文件,以及与它们相关的后台(code behind )类文件(可以用VB, C#, Ruby 或Python来编写):
XAML文件是XML文本文件,可以用来用声明的方式指定 Silverlight 或 WPF应用的用户界面。XAML还可更广泛地用来用声明的方式代表.NET对象。
App.xaml 文件一般用来声明譬如象画刷和样式对象这样可在整个应用中共享的资源。App.xaml的后台Application类可用来处理应用级的事件,象 Application_Startup, Application_Exit 和Application_UnhandledException。
Page.xaml 文件,在默认情形下,是在应用激活时装载的起始的UI控件。在其中,我们可以使用UI控件来定义我们的用户界面,然后在Page的后台代码类里处理它们的事件(详见后文)。
在我们编译DiggSample项目时,在默认情形下,Visual Studio 会把代码和XAML标识编译进一个标准的 .NET 程序集文件中,然后把它和任何静态的资源(象图片或我们想要包含的静态文件)包装进硬盘上一个叫做“DiggSample.xap”的文件中去:
“.xap”文件(其音发作“zap”)使用标准的 .zip压缩算法来减小客户端下载的大小。一个“hello world”.NET Silverlight 应用(用VB或C#编写的)其大小大概为4KB。
要宿主和运行一个Silverlight 2 应用,你可以把
虽然在很多方面,Silverlight表现出了比Flash更佳的性能,例如与AJAX结合更紧密,更容易动态生成,对搜索引擎更友好,开发工具集成度更高,等等。本文作者还是从以下四个方面列举了Silverlight无法取代Flash的理由。
技术潜力
对于一个专业开发者,在考虑选择哪门技术的时候,很重要的一个方面就是这门技术的发展潜力。包括它的改善空间、提升余地,以及你投入时间掌握这门技术后获得的经济回报。
在短时间内,Silverlight会表现出强大的潜力。微软是一家资本雄厚的大公司,典型的微软模式就是,微软会为Silverlight砸很多钱,让人们相信这是一门值得学习的技术。我知道有许多Flash开发者已经通过开发Silverlight项目赚取了可观的收入,这些项目是由Redmond直接或间接援助的。Adobe在这个方面完全不能和微软竞争。虽然Adobe也有雄厚的资金,但还远比不上微软那样富到可以买上一个小国家。
从长远来看,人们从Silverlight开发中学到的基本知识也不会昙花一现。但是,如果你真的对开发跨平台交互式WEB感兴趣,Silverlight技术未来将会在很大程度上把你的成功锁定在同一个平台(Windows)上。
小结:Flash也许没有如Silverlight淘金般的发展潜力,但它是一门非常确立和成熟的技术(98%的安装基础,其中85%以上是Flash Player 9版本),它还会继续扩大它的使用范围,并在相当长的时间内在开发交互式Web领域稳定增长。当前微软在推动Silverlight发展方面投入了大量的金钱,但是在未来如果微软不再象现在这样往里面砸钱的话,Silverlight的前景就另人担忧了。
运行时
大多数对这两门技术的讨论都集中在其虚拟机的性能上。很正常,一个平台的成功性在很大程度上决定于它的性能。对于Silverlight,我并不是了解太多,但从现有资料看来,当前1.0beta VM基本上是SVG/WM接口。它并不支持构件(AKA controls),没有现成的语言解释器,也没有太多另人兴奋的亮点。而在新发布的α版Silverlight 1.1中这些方面有了明显的改进。但是Adobe在这方面还是处于领先地位,成熟的跨平台开发体验,对目标市场也有更深入的理解。
接口大小和实用性也是考察的重要因素。Flash player,包括两个虚拟机、大量的功能程序,只有2MB,功能残缺不全的Silverlight1.0 beta是1.2MB(Mac上是5.3MB)。支持动态语言运行的α版Silverlight 1.1扩大到4.2MB(Mac上是10.3MB),如果要浏览Managed SilverLight的网页,就得下载这个Runtime,这对于储存空间拮据的手机系统来说,还是稍嫌庞大些。我预计将来还会更加庞大。接口大小在几年前也许还不是什么大问题,但它仍然会对接受度有很大的影响。在另一个方面说来,与网络相连的电脑上已经有98%都安装了Flash player了,它能自动更新,可以在Windows、Mac和Lunix上运行,是发布后升级最迅速的软件产品(前提是用户接受新版本)。
小结:如果微软在这些方面继续改进,Silverlight会有非常大的潜力。不幸的是,我看到他们动作缓慢。Adobe仍大规模的领先,在实用性和普及率方面。
开发工具
我看过Expression suite,它给我留下了深刻印象,微软对它做了很大的改善。他们从Adobe的成功中学习长处并改进了其缺点。微软有许多开发实用开发工具的经验,这在它们的Expression工具中就可以看出。在这方面,Adobe并没有太多创建开发工具的经验。微软正在对Expression进行更新。Adobe也在做着一件深远的事,就是集成他们的开发工具创建一个凝聚性的工作流。
从另一个角度,微软并没有开发设计工具的经验,事实上他们对设计者还不够了解。他们的工具只能在Windows平台上使用,这从一开始就切断了一半的设计者市场。在今年的微软MIX大会上,一位参会者在会间询问Lynda(Lynda.com站长),如果设计者们熟悉Expression后将如何转到Windows平台上去。她回答说她自己就是个Mac用户,但她不会转到Windows上去。我为Lynda的诚实鼓掌,我相信这也清楚的证实了微软要想让抵制者们改变原来的工具并不是一件容易的事。
小结:微软将会建立更完善的开发工具集,并提供更佳的集成工具。但是,他们事实上是不愿意支持Macs的,他们并不能深入的理解创造性和设计者是他们的要害。Adobe对创造的流程有很深入的理解,它们对跨平台的支持性是微软不能比敌的。
未来趋势
虽然很容易被忽视,但这是一个非常重要的问题。为什么微软会构造Silverlight?微软的长远意图是什么?现在主要猜测是用来抢占Flash的RIA应用市场,但根据过去的观察,微软的行动一直很稳健,我想这一次也不会例外。
微软因为其经常会在一项技术已被事实证明是成功后,再进入这个领域而臭名昭著,他们会扔进大量的金钱逐渐去扼杀竞争,一旦形成垄断,技术的发展就会遇到很大的阻碍。微软也经常会因一时的怪念头而放弃对跨平台特性的支持。确实,他们提供的很多跨平台产品到最后都会因为某种冠冕堂皇的理由被抛弃或半途而废(MAPI in Entourage, IE, VBScript in Office, Windows Media versioning and DRM, heck, 甚至Halo)。
Adobe也不是慈善家,但他们已经证明自己的产品能够成功的支持跨平台特性,即使在交互式WEB页面开发上真正意义上的竞争者并不多,但Adobe一直在对产品进行改进。Silverlight会迫使他们做的更好。举个例子,如果没有Silverlight的出现,我们能否如此快的在Linux上看到Flash player9也将会是个疑问。
小结:如果消灭掉了Flash,继续追求跨平台特性就不会是微软最佳利益的选择了,也很难保证持续对其革新。做为一个长期的Mac用户,我真的不能相信微软的意图,但是看到在Silverlight的压力下Adobe的持续改进也是一件另人高兴的事。
结论:总的说来,我相信Silverlight的潜力,尤其在短期内微软砸进大量金钱的效果会比较明显。在不远的将来,微软的开发工具也可能会更加健壮,比起Adobe提供的工具有更高的集成度,但是仅仅支持Windows平台的特性会让大量的开发者和设计者与Silverlight保持距离。我相信Silverlight接口将会是一个合适的运行时程序,但它不会象Flash player那样打包到用字节计算,也决不会达到象Flash那样的安装普及率。总之,希望silverlight越走越好,因为对于程序员来说,多个选择,不是坏事。
Silverlight是用XAML语言来描述界面的。XAML是eXtensible Application Markup Language的缩写,也就是可扩展的应用程序标记语言。在WPF(Windows Presentation Foundation)中,第一次出现了XAML,用来描述.NET语言。而Silverlight中的XAML只用来对用户界面作出统一的描述,弥补HTML/CSS等在界面定制上的不足,并使开发人员和设计人员可以运用同一种语言进行交流,减少额外的工作量。因此,Silverlight XAML的语法相对WPF中的XAML相对要简单一些,也更容易上手。
虽然我们可以使用Microsoft Expression Studio的视觉化方式设计界面,但是了解XAML的基本语法可以帮助我们更好的定制自己的界面。如果想要直接编写XAML,使用Visual Studio 2008则可以提高编写的效率,因为里面有自动感应功能(Intellisense)。
2. Canvas容器和各种元素
任何Silverlight应用程序的界面描述都是以一个叫Canvas(画布)的容器为根开始的。当我们在Microsoft Expression Blend或者Visual Studio 2008中创建一个新的Silverlight项目后,总会生成一个只包含根Canvas的.xaml文件,如下所示:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="SilverlightTestProject.Page;assembly=ClientBin/SilverlightTestProject.dll"
Width="640"
Height="480"
Background="White">
</Canvas>
任何元素都必须添加在这个根Canvas容器的里面,因为一个界面里只能有一个这样的根Canvas容器。我们可以在这个根容器里加入子容器或者其他元素。每个元素都有一个标签相对应。比如在子容器中添加一个矩形,并在根容器中添加一个椭圆形:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="SilverlightTestProject.Page;assembly=ClientBin/SilverlightTestProject.dll"
Width="640"
Height="480"
Background="White">
<Canvas>
<Rectangle></Rectangle>
</Canvas>
<Ellipse></Ellipse>
</Canvas>
Silverlight定义的常见的几何图形包括矩形
3. 附加元素属性
尝试以上代码,可以发觉我们其实看不到任何我们想要的性状,因为它们的默认的大小属性均为0。可见,仅使用这些元素标签还不足以得到我们想要得形状,我们需要在标签中设置它的属性值,确定它的大小、位置等等。
观察根Canvas,我们已经可以了解到一些属性的定制,比如只在根节点出现的定义xml名字空间(xmlns)以及自定义的xml名字空间(xmlns:x)。其中还有一些常用的属性,如宽(Width),高(Height)。在Canvas中,这两个属性既可以用像素值来表示,也可以用百分比来表示。x:Name表示该元素示例的名称,有了这个名称,我们就可以在.NET代码中操作这个元素示例。Background属性设置了背景的颜色,不设置这个值,则该元素透明。
每个元素都有属于自己的一组属性。比如,我们可以将刚才的代码改进一下:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="SilverlightTestProject.Page;assembly=ClientBin/SilverlightTestProject.dll"
Width="640"
Height="480"
Background="White">
<Canvas x:Name="subCanvas" Canvas.Left="123" Canvas.Top="117" Width="53" Height="39">
<Ellipse Fill="Yellow" Height="100" Width="200" StrokeThickness="2" Stroke="Black"/>
</Canvas>
<Rectangle x:Name="myRect" Canvas.Top="20" Canvas.Left="20" Width="100" Height="100" Fill="Blue" Stroke="Red" StrokeThickness="3" />
</Canvas>
则可以看到以下效果:
其中Fill指定了填充色,Stroke和StrokeThickness定制了形状的轮廓线条的颜色和粗细。我们可以看到根Canvas下的子元素(包括子容器Canvas)的位置属性均表示相对上一级Canvas的坐标位置。值得注意的是这里虽然矩形myRect超出了subCanvas定义的边界范围,但它并不会被subCanvas剪裁,且仍属于subCanvas中的元素。
顺便一提,目前我们只有Canvas一种容器,在不久的将来,Silverlight将会提供更多的容器,使布局管理更方便。
4. 对象模型
在WPF中,XAML是.NET代码的xml表现形式;而在Silverlight中,我们同样有与XAML相对应的.NET语言编程方式。其中,每一个元素对应一个对象,元素属性在其.NET对象中都有对应的属性。例如先前一个例子中的矩形就可以用以下C#语言来表示:
myRect .SetValue(Canvas.TopProperty, 117);
myRect .SetValue(Canvas.LeftProperty, 123);
myRect .Width = 100;
myRect .Height = 100;
SolidColorBrush brushBlue = new SolidColorBrush();
brushBlue.Color = Colors.Blue;
myRect .Fill = brushBlue;
SolidColorBrush brushRed = new SolidColorBrush();
brushRed.Color = Colors.Red;
myRect .Stroke = brushRed;
myRect .StrokeThickness = 3;
这里SolidColorBrush对象派生自Brush,是画刷的一种。Silverlight里定义了好几种不同的画刷对图形进行填充。属性Fill的默认画刷是SolidColorBrush,因此可以在.xaml文件中可以直接给Fill属性赋值,但在.NET语言中则必须明确指出画刷的类型。有关画刷的具体内容我们会在以后介绍。
刚才用C#定义出来的矩形还是独立的,如果要把它在界面上表示出来,则需要在其后加上下面这句代码将矩形加入上一级Canvas中:
从今天开始,让我们系统的了解一下如何用.NET语言来开发Silverlight的应用程序。这个入门系列会包含用.NET语言(这里主要使用C#语言)开发Silverlight应用程序的各个方面,如UI控制、自定义控件、与HTML及Script语言的集成应用、HTTP网络存取等等。如果大家有什么感兴趣的话题也可以提出来。由于Silverlight 1.1还处于Alpha版本,.NET语言中关于Silverlight的一些API可能会与将来的正式版本中有些出入,但是大多数基本的东西还是不变的。
使用.NET语言开发Silverlight应用程序入门之一:了解项目结构今天先让我们从Silverlight应用程序的.NET项目结构开始,看一下这样的一个项目中包含了些什么文件,这些文件分别是用来做什么的。了解这些内容有助于我们将来根据自己的需要制作更为复杂的项目内容。在开始介绍之前,请务必安装Silverlight 1.1 Alpha Refresh。
无论是Silverlight 1.0还是1.1版本,一个Silverlight项目总是包含以下几种文件:
- 嵌入Silverlight应用程序的html文件。
- 用来执行Silverlight应用程序载入工作的JavaScript文件。
- 定义和描述应用程序界面的XAML文件。
如果是.NET的项目,界面描述中所定义的新类型都包含在程序集(assembly)文件中。
我们可以用Microsoft Expression Blend 2 (目前最新的预览版本是September Preview)或者Visual Studio 2008 Beta2 (需安装好Silverlight Tool Alpha)来创建一个新.NET的项目。创建成功后,我们就可以看到一个Silverlight的.NET项目包含了如下的目录结构:
- References目录
查看该目录,我们可以看到其中包含了许多 (.dll)文件,这些文件定义了项目中所引用的各托管类型。如果我们要使用其他自定义的类型,就可能需要手动添加包含该类型定义的.dll文件。 若Silverlight插件中没有包含项目所引用的某些程序集文件,则应用程序用户需要下载这些程序集文件到本地。 - Page.xaml
项目默认的主界面的XAML描述文件。- Page.xaml.cs
每个xaml文件之后都有一个对应的.NET语言文件。由于我们创建的是C#项目,所以其对应的文件为.cs文件。这个文件对.xaml文件中的所引用的.NET类型做了定义。 通过编译之后,项目会生成程序集文件,供.xaml文件引用,且该程序集文件会随Silverlight应用程序一起下载到用户本地。
- Page.xaml.cs
- Silverlight.js
该文件包含了运行Silverlight应用程序之前所必需的各种操作,主要检查用户是否安装了符合版本需求的Silverlight。如果没有安装,则Silverlight应用程序所在的页面将会显示图标,提示用户先安装插件。这里我们不建议Silverlight的开发设计人员改变该.js文件的内容。 - TestPage.html(Blend 2中创建的文件名为Default.html)
该文件为项目的默认主页,文件中引入了Silverlight的脚本文件来载入Silverlight应用程序。- TestPage.html.js(Blend 2中的文件名为Default_html.js)
该文件中定义了TestPage.html中调用的CreatSilverlight()方法来载入Silverlight应用程序。
- TestPage.html.js(Blend 2中的文件名为Default_html.js)
让我们再具体的看一看其中一些文件所包含的内容:
- TestPage.html
<html>
<head>
<title>Silverlight Project Test Page </title>
<script type="text/javascript" src="Silverlight.js" mce_src="Silverlight.js"></script>
<script type="text/javascript" src="TestPage.html.js" mce_src="TestPage.html.js"></script>
<style type="text/css">
<!--设置应用程序在html页面中显示的大小,也可以用百分比表示,设置为100%则应用程序为自适应大小-->
.silverlightHost { width: 640px; height: 480px; }
</style>
</head>
<body>
<!--以下的ID用来标示DIV,尤其当页面总有多个Silverlight实例时,这个ID就成为了标示每个Silverlight应用程序的重要标志-->
<div id="SilverlightControlHost" class="silverlightHost" >
<script type="text/javascript">
createSilverlight();
</script>
</div>
</body>
</html>
- TestPage.html.js
//creatSilverlight函数用来执行载入Silverlight应用程序的操作及相关属性
function createSilverlight()
{
Silverlight.createObjectEx({
//指定了初始化载入的应用程序页面
source: "Page.xaml",
parentElement: document.getElementById("SilverlightControlHost"),
id: "SilverlightControl",
properties: {
width: "100%",
height: "100%",
version: "1.1",
enableHtmlAccess: "true"
},
events: {}
});
// 下面的函数是默认将键盘焦点集中在Silverlight应用程序上
document.body.onload = function() {
var silverlightControl = document.getElementById('SilverlightControl');
if (silverlightControl)
silverlightControl.focus();
}
}
- Page.xaml
<!--Canvas是一个包含了各种控件和元素的容器,每个Silverlight应用程序都有一个XAML的根文件,每个XAML文件的根都是一个Canvas容器,且只能有一个作为根元素的Canvas容器-->
<Canvas x:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<!--指定当Load事件发生时所要载入的方法-->
Loaded="Page_Loaded"
<!--指定该.xaml文件中的托管类进入点,以及所涉及到的引用(程序集)的位置,一般项目编译生成的程序集文件都位于项目中的ClientBin文件夹中-->
x:Class="SilverlightProjectStructure.Page;assembly=ClientBin/SilverlightProjectStructure.dll"
Width="640"
Height="480"
Background="White"
>
</Canvas>
- Page.xaml.cs
public partial class Page : Canvas
{
//载入应用程序时的初始化方法,该方法中包含了所有页面初始化是所要做的操作
public void Page_Loaded(object o, EventArgs e)
{
// 初始化变量时,以下方法必不可少
InitializeComponent();
//接下来指定其他所需的初始化操作……
}
}
Page.xaml如下:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="187" Height="97">
<Canvas x:Name="EClock" Height="97" Width="187" >
</Canvas>
</UserControl>
Page.xaml.cs如下:
using System;
using System.Collections.Generic;
using System.Linq;
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.Markup; 
namespace OpenXmlVideo2
{
public partial class Page : UserControl
{
private TextBlock textBlock1;
private System.Windows.Threading.DispatcherTimer timer; 
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded); 
} 
void Page_Loaded(object sender, RoutedEventArgs e)
{
string xaml = string.Empty;
xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/client/2007\" Margin=\"14,11,19,12\" Name=\"textBlock1\" FontFamily=\"Time New Roman\" FontSize=\"40\">00:00:00</TextBlock>";
textBlock1 = XamlReader.Load(xaml) as TextBlock;
//Loaded就是TextBlock的加载事件,那么里面的textBlock1_Loaded自然就是事件处理程序的名称。
textBlock1.Loaded += new RoutedEventHandler(textBlock1_Loaded);
//改变附加属性(attached properties),必须使用SetValue方法
textBlock1.SetValue(Canvas.LeftProperty, 2);
textBlock1.SetValue(Canvas.TopProperty, 2);
//加把textBlock1对象做为子对象添加到画布(和asp.net页的控件树的道理相拟)
this.EClock.Children.Add(textBlock1);
} 
void textBlock1_Loaded(object sender, RoutedEventArgs e)
{
//使用了DispatcherTimer,我把间隔设置为1秒。该计时器的间隔事件也是Tick事件
timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1); //间隔1秒
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
} 
void timer_Tick(object sender, EventArgs e)
{
textBlock1.Text = DateTime.Now.ToLongTimeString();
}
}
}
Silverlight被称为是“C#的Flash杀手”,结果证明它是一个很有趣的技术,看起来也确实像是“Flash杀手”。给浏览器下载一个plugin,就可以马上看到所谓的“富互联网应用”,包括有声录影(Movie Clips)、矢量图形(Vector Graphics)等。
Silverlight使用的是一种基于XML的语言叫XAML,所有代码可以在.NET上实现,那意味着C#代码可以编译和运行在浏览器内的CLR。非常酷。而且更好的是,它不仅可运行于IE浏览器,而且可运行于Firefox甚至Safari。功能差不多的运行在Linux上的版本称为Moonlight,也是来自于微软的支持。
以下是我使用Silverlight的一些看法:
非常有趣且易学;
看起来像是一个真正的开发工具,因为它基于VS2008、XAML和C#(或者VB);
IE 7 的plugin比较费时间,无论是1.0还是1.1 alpha版;
1.1 alpha版的Codebase和documentation远不够完善,期待中;
还有许多我希望能够被包含的特征以及预告中透露的,我也在期待。
Silverlight是仍在完善中的一个东西,预计在2008年第一季度推出新beta即Silverlight 2.0,届时将包含许多特性。在我看来,silverlight将在2008年夏天的时候成为一个“真正的”产品,问题是:它会成为Flash 杀手吗?随着Flash新版本的不断出现,时间将揭晓答案。








