很多人都已经开始了SilverLight的学习,虽然对于M$的产品需要牺牲很多小白鼠才能够比较稳定,今天我也来当当小白鼠。我选择的是SilverLight1.1(C#)当然是Alpha版本的,虽然JS在Orcas([JS.IntelliSense]VS2008(Orcas) So Cool)中也已经不算什么难的事情了,但是我还是觉得C#比较好一点。当我装上SilverLight开发所需要的所有器械后,拿出来的第一个Getting started例子就是Clock,但是惨不忍睹啊,编译通不过。对于第一次学习这个东东,我哪知道错在什么地方,好像那个例子是用JS写后改过来的,总之在我用是就不能通过了。还好找到了另一篇文章来帮助我完成了这个例子,OK,闲话不多说了,本文将讲解SilverLight的几个基础,并一步一步的带你走完“模拟时钟”。
首先我们新建一个silverLight项目,在C#语言选择栏下面可以找到SilverLight然后建立项目Clock。Orcas会为我们生成几个文件,我们就可以直接利用他们来为我们完成这个学习例子。
从上面我们可以看出Page.xaml就是我们所要讲的主角,Page.xaml.cs是处理Page.xaml文件的(aspx,aspx.cs),silverlight.js是我们创建控件是要用的脚本,还有一个脚本是在TestPage.html中创建当前控件用的。OK我们打开Page.xaml看看他们为我们做好了什么?代码如下:
和ASP.NET中aspx页面一样,每一个元素都与.NET CLR类关联。 从上面的代码 我们可以看出xmlns为XML命名空间,至于有什么用处其实我也说不清,反正他自动增加的就放着吧。我们可以看到上面有一个以"x:"为前缀的属性(如果是我们自己写的就用其他前缀,和ASP.NET中自定义服务器控件注册一样),这个相当于ASP.NET中的"asp:"前缀就是注册了控件一样,也就是说以"x:"为前缀的属性在服务端可以获取,例如上面的"x:Name"在服务端就会为我们生成一个ID,我们可以通过这个ID来调用当前XAML(相当于ASP.NET服务器控件中的ID),x:Class是表示当前XAML和哪个类相关联。
我们还可以引入一个程序集,我们自己的类等等,值得注意的是Loaded这个属性的值和Page.xaml.cs中的方法是一至的,如果不一致将出现错误。OK接下来我们来看看这个例子,这个例子的最终效果图如下:
万丈高楼平地起,我们写这个程序当然也是要从底层做起,我用Blend2 May 2007打开但是不怎么会用,虽然画了图但是不知道怎么去颜色,怎么填充颜色,所以还是一步一步的建起。首先我们要画出最底层的阴影,代码如下:
你可以按F5看看效果,从上面可以知道,我们画了一个宽高为305(直径)的圆,其中圆的顶端据canvas的距离是117,左边据canvas的距离也为117,不透明度为0.3。通过上面的说明大家也应该知道各个属性的用途了,这里就不多说了。我们可以看到如下效果:
接着我们通过设置StrokeThickness(厚度:我也不知道怎么说,总之是内圆和外圆半径差值)来画一个环形,然后设定两端颜色线性渐变。代码如下:
我们可以按F5看看效果,是不是我们想象的那样,如果我猜的没有错的话Ellipse.Stroke是取得圆环部分,通过LinearGradientBrush刷子来进行填涂(不知道用什么术语),然后设置起点和终点的颜色等,效果如下:
然后我们在添加圆上的线,用黑色画圈这样显得更好看一点,以同样的原理画厚度为10的环形,在加入圆圈线等,代码如下:
按F5可以看到如下效果:
现在我们所剩下的工作就是画上指针hour,minute,second。用 Polygon可以画多边形,通过 Points属性来确定断点坐标。我们在通过 Line来画线(second), 代码如下:
我们可以看到效果如下:
这个是不会动的始钟,下面我们要做的是就是让时钟走起来,所以要涉及到行为等问题,我们在上面定义时钟指针时都有给他们加入x:Name属性,也就是说我们给他们一个ID。我们可以将事件绑定到指针中(事件触发器),代码如下:
从上述代码中我们可以知道,这个时间触发的事件由 Canvas.Loaded来触发,这个对应的是<Canvas/>的Loaded属性。然后我们通过DoubleAnimation来管理各个控件,Storyboard.TargetName和刚刚画好的控件绑定,将Storyboard.TargetProperty设置为角度"Angle",永远的重复执行,就是将RepeatBehavior设置为Forever,Duration设置为什么时候是才是一圈(可能是这样,太晚了不查资料了...)。接下来要做的就是通过cs文件来控制转速,代码如下,谁都看得懂:
首先我们新建一个silverLight项目,在C#语言选择栏下面可以找到SilverLight然后建立项目Clock。Orcas会为我们生成几个文件,我们就可以直接利用他们来为我们完成这个学习例子。
从上面我们可以看出Page.xaml就是我们所要讲的主角,Page.xaml.cs是处理Page.xaml文件的(aspx,aspx.cs),silverlight.js是我们创建控件是要用的脚本,还有一个脚本是在TestPage.html中创建当前控件用的。OK我们打开Page.xaml看看他们为我们做好了什么?代码如下:
1
<
Canvas
2 xmlns ="http://schemas.microsoft.com/client/2007"
3 xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
4 x:Name ="parentCanvas"
5 Loaded ="Page_Loaded"
6 x:Class ="Clock.Page;assembly=ClientBin/Clock.dll"
7 Width ="640"
8 Height ="480"
9 Background ="White"
10 >
11
12 </ Canvas >
2 xmlns ="http://schemas.microsoft.com/client/2007"
3 xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
4 x:Name ="parentCanvas"
5 Loaded ="Page_Loaded"
6 x:Class ="Clock.Page;assembly=ClientBin/Clock.dll"
7 Width ="640"
8 Height ="480"
9 Background ="White"
10 >
11
12 </ Canvas >
和ASP.NET中aspx页面一样,每一个元素都与.NET CLR类关联。 从上面的代码 我们可以看出xmlns为XML命名空间,至于有什么用处其实我也说不清,反正他自动增加的就放着吧。我们可以看到上面有一个以"x:"为前缀的属性(如果是我们自己写的就用其他前缀,和ASP.NET中自定义服务器控件注册一样),这个相当于ASP.NET中的"asp:"前缀就是注册了控件一样,也就是说以"x:"为前缀的属性在服务端可以获取,例如上面的"x:Name"在服务端就会为我们生成一个ID,我们可以通过这个ID来调用当前XAML(相当于ASP.NET服务器控件中的ID),x:Class是表示当前XAML和哪个类相关联。
我们还可以引入一个程序集,我们自己的类等等,值得注意的是Loaded这个属性的值和Page.xaml.cs中的方法是一至的,如果不一致将出现错误。OK接下来我们来看看这个例子,这个例子的最终效果图如下:
万丈高楼平地起,我们写这个程序当然也是要从底层做起,我用Blend2 May 2007打开但是不怎么会用,虽然画了图但是不知道怎么去颜色,怎么填充颜色,所以还是一步一步的建起。首先我们要画出最底层的阴影,代码如下:
1
<
Ellipse
2 Height ="305"
3 Width ="305"
4 Fill ="Black"
5 Canvas.Left ="117"
6 Canvas.Top ="117"
7 StrokeThickness ="0"
8 Opacity ="0.3" />
2 Height ="305"
3 Width ="305"
4 Fill ="Black"
5 Canvas.Left ="117"
6 Canvas.Top ="117"
7 StrokeThickness ="0"
8 Opacity ="0.3" />
你可以按F5看看效果,从上面可以知道,我们画了一个宽高为305(直径)的圆,其中圆的顶端据canvas的距离是117,左边据canvas的距离也为117,不透明度为0.3。通过上面的说明大家也应该知道各个属性的用途了,这里就不多说了。我们可以看到如下效果:
接着我们通过设置StrokeThickness(厚度:我也不知道怎么说,总之是内圆和外圆半径差值)来画一个环形,然后设定两端颜色线性渐变。代码如下:
1
<
Ellipse
2 Height ="300"
3 Width ="300"
4 Canvas.Left ="115"
5 Canvas.Top ="115"
6 Fill ="Black"
7 StrokeThickness ="20" >
8 < Ellipse .Stroke >
9 < LinearGradientBrush >
10 < LinearGradientBrush .GradientStops >
11 < GradientStop Color ="Red" Offset ="0.1" />
12 < GradientStop Color ="Orange" Offset ="0.95" />
13 </ LinearGradientBrush.GradientStops >
14 </ LinearGradientBrush >
15 </ Ellipse.Stroke >
16 </ Ellipse >
2 Height ="300"
3 Width ="300"
4 Canvas.Left ="115"
5 Canvas.Top ="115"
6 Fill ="Black"
7 StrokeThickness ="20" >
8 < Ellipse .Stroke >
9 < LinearGradientBrush >
10 < LinearGradientBrush .GradientStops >
11 < GradientStop Color ="Red" Offset ="0.1" />
12 < GradientStop Color ="Orange" Offset ="0.95" />
13 </ LinearGradientBrush.GradientStops >
14 </ LinearGradientBrush >
15 </ Ellipse.Stroke >
16 </ Ellipse >
我们可以按F5看看效果,是不是我们想象的那样,如果我猜的没有错的话Ellipse.Stroke是取得圆环部分,通过LinearGradientBrush刷子来进行填涂(不知道用什么术语),然后设置起点和终点的颜色等,效果如下:
然后我们在添加圆上的线,用黑色画圈这样显得更好看一点,以同样的原理画厚度为10的环形,在加入圆圈线等,代码如下:
1
<
Ellipse
Height
="300"
Width
="300"
Canvas.Left
="115"
Canvas.Top
="115"
StrokeThickness
="1"
Stroke
="Black"
/>
2
3 < Ellipse
4 Height ="260"
5 Width ="260"
6 Canvas.Left ="135"
7 Canvas.Top ="135"
8 StrokeThickness ="1"
9 Stroke ="Black" />
10
11 < Ellipse
12 Width ="260"
13 Height ="260"
14 Canvas.Left ="135"
15 Canvas.Top ="135"
16 StrokeThickness ="10" >
17 < Ellipse .Stroke >
18 < LinearGradientBrush >
19 < LinearGradientBrush .GradientStops >
20 < GradientStop Color ="Green" Offset ="0.05" />
21 < GradientStop Color ="Yellow" Offset ="0.95" />
22 </ LinearGradientBrush.GradientStops >
23 </ LinearGradientBrush >
24 </ Ellipse.Stroke >
25 </ Ellipse >
26
27 < Ellipse Width ="260" Height ="260" Stroke ="Black" Canvas.Left ="135" Canvas.Top ="135" StrokeThickness ="1" />
28
29 < Ellipse Width ="240" Height ="240" Stroke ="Black" Canvas.Left ="145" Canvas.Top ="145" StrokeThickness ="1" />
30
2
3 < Ellipse
4 Height ="260"
5 Width ="260"
6 Canvas.Left ="135"
7 Canvas.Top ="135"
8 StrokeThickness ="1"
9 Stroke ="Black" />
10
11 < Ellipse
12 Width ="260"
13 Height ="260"
14 Canvas.Left ="135"
15 Canvas.Top ="135"
16 StrokeThickness ="10" >
17 < Ellipse .Stroke >
18 < LinearGradientBrush >
19 < LinearGradientBrush .GradientStops >
20 < GradientStop Color ="Green" Offset ="0.05" />
21 < GradientStop Color ="Yellow" Offset ="0.95" />
22 </ LinearGradientBrush.GradientStops >
23 </ LinearGradientBrush >
24 </ Ellipse.Stroke >
25 </ Ellipse >
26
27 < Ellipse Width ="260" Height ="260" Stroke ="Black" Canvas.Left ="135" Canvas.Top ="135" StrokeThickness ="1" />
28
29 < Ellipse Width ="240" Height ="240" Stroke ="Black" Canvas.Left ="145" Canvas.Top ="145" StrokeThickness ="1" />
30
按F5可以看到如下效果:
现在我们所剩下的工作就是画上指针hour,minute,second。用 Polygon可以画多边形,通过 Points属性来确定断点坐标。我们在通过 Line来画线(second), 代码如下:
1
<
Polygon
x:Name
="Minutes"
2 Canvas.Left ="265" Canvas.Top ="265"
3 Points ="0,0 10,-10 0,-115 -10,-10"
4 Stroke ="Green" StrokeThickness ="2" Opacity ="0.8" >
5 < Polygon .RenderTransform >
6 < RotateTransform
7 x:Name ="MinutesAngle" CenterX ="0" CenterY ="0" />
8 </ Polygon.RenderTransform >
9 < Polygon .Fill >
10 < LinearGradientBrush >
11 < LinearGradientBrush .GradientStops >
12 < GradientStop Color ="Green"
13 Offset ="0.05" />
14 < GradientStop
15 Color ="Yellow" Offset ="0.95" />
16 </ LinearGradientBrush.GradientStops >
17 </ LinearGradientBrush >
18 </ Polygon.Fill >
19 </ Polygon >
20
21 < Polygon x:Name ="Hours" Canvas.Left ="265"
22 Canvas.Top ="265" Points ="0,0 10,-10 0,-90 -10,-10"
23 Stroke ="Green" StrokeThickness ="2" Opacity ="0.8" >
24 < Polygon .RenderTransform >
25 < RotateTransform
26 x:Name ="HoursAngle" CenterX ="0" CenterY ="0" />
27 </ Polygon.RenderTransform >
28 < Polygon .Fill >
29 < LinearGradientBrush >
30 < LinearGradientBrush .GradientStops >
31 < GradientStop Color ="Green" Offset ="0.05" />
32 < GradientStop Color ="Yellow" Offset ="0.95" />
33 </ LinearGradientBrush.GradientStops >
34 </ LinearGradientBrush >
35 </ Polygon.Fill >
36 </ Polygon >
37
38 < Line x:Name ="Seconds" Canvas.Left ="265"
39 Canvas.Top ="265" X1 ="0" Y1 ="0" X2 ="0"
40 Y2 ="-120" Stroke ="Red" StrokeThickness ="3" >
41 < Line .RenderTransform >
42 < RotateTransform
43 x:Name ="SecondsAngle" CenterX ="0" CenterY ="0" />
44 </ Line.RenderTransform >
45 </ Line >
2 Canvas.Left ="265" Canvas.Top ="265"
3 Points ="0,0 10,-10 0,-115 -10,-10"
4 Stroke ="Green" StrokeThickness ="2" Opacity ="0.8" >
5 < Polygon .RenderTransform >
6 < RotateTransform
7 x:Name ="MinutesAngle" CenterX ="0" CenterY ="0" />
8 </ Polygon.RenderTransform >
9 < Polygon .Fill >
10 < LinearGradientBrush >
11 < LinearGradientBrush .GradientStops >
12 < GradientStop Color ="Green"
13 Offset ="0.05" />
14 < GradientStop
15 Color ="Yellow" Offset ="0.95" />
16 </ LinearGradientBrush.GradientStops >
17 </ LinearGradientBrush >
18 </ Polygon.Fill >
19 </ Polygon >
20
21 < Polygon x:Name ="Hours" Canvas.Left ="265"
22 Canvas.Top ="265" Points ="0,0 10,-10 0,-90 -10,-10"
23 Stroke ="Green" StrokeThickness ="2" Opacity ="0.8" >
24 < Polygon .RenderTransform >
25 < RotateTransform
26 x:Name ="HoursAngle" CenterX ="0" CenterY ="0" />
27 </ Polygon.RenderTransform >
28 < Polygon .Fill >
29 < LinearGradientBrush >
30 < LinearGradientBrush .GradientStops >
31 < GradientStop Color ="Green" Offset ="0.05" />
32 < GradientStop Color ="Yellow" Offset ="0.95" />
33 </ LinearGradientBrush.GradientStops >
34 </ LinearGradientBrush >
35 </ Polygon.Fill >
36 </ Polygon >
37
38 < Line x:Name ="Seconds" Canvas.Left ="265"
39 Canvas.Top ="265" X1 ="0" Y1 ="0" X2 ="0"
40 Y2 ="-120" Stroke ="Red" StrokeThickness ="3" >
41 < Line .RenderTransform >
42 < RotateTransform
43 x:Name ="SecondsAngle" CenterX ="0" CenterY ="0" />
44 </ Line.RenderTransform >
45 </ Line >
我们可以看到效果如下:
这个是不会动的始钟,下面我们要做的是就是让时钟走起来,所以要涉及到行为等问题,我们在上面定义时钟指针时都有给他们加入x:Name属性,也就是说我们给他们一个ID。我们可以将事件绑定到指针中(事件触发器),代码如下:
1
<
Canvas
.Triggers
>
2 < EventTrigger RoutedEvent ="Canvas.Loaded" >
3 < EventTrigger .Actions >
4 < BeginStoryboard >
5 < Storyboard x:Name ="ClockAnimation" >
6 < DoubleAnimation x:Name ="SecondsAnim"
7 Storyboard.TargetName ="SecondsAngle"
8 Storyboard.TargetProperty ="Angle"
9 RepeatBehavior ="Forever" Duration ="00:01:00" />
10 < DoubleAnimation x:Name ="MinutesAnim"
11 Storyboard.TargetName ="MinutesAngle"
12 Storyboard.TargetProperty ="Angle"
13 RepeatBehavior ="Forever" Duration ="1:00:00" />
14 < DoubleAnimation x:Name ="HoursAnim"
15 Storyboard.TargetName ="HoursAngle"
16 Storyboard.TargetProperty ="Angle"
17 RepeatBehavior ="Forever" Duration ="12:00:00" />
18 </ Storyboard >
19 </ BeginStoryboard >
20 </ EventTrigger.Actions >
21 </ EventTrigger >
22 </ Canvas.Triggers >
2 < EventTrigger RoutedEvent ="Canvas.Loaded" >
3 < EventTrigger .Actions >
4 < BeginStoryboard >
5 < Storyboard x:Name ="ClockAnimation" >
6 < DoubleAnimation x:Name ="SecondsAnim"
7 Storyboard.TargetName ="SecondsAngle"
8 Storyboard.TargetProperty ="Angle"
9 RepeatBehavior ="Forever" Duration ="00:01:00" />
10 < DoubleAnimation x:Name ="MinutesAnim"
11 Storyboard.TargetName ="MinutesAngle"
12 Storyboard.TargetProperty ="Angle"
13 RepeatBehavior ="Forever" Duration ="1:00:00" />
14 < DoubleAnimation x:Name ="HoursAnim"
15 Storyboard.TargetName ="HoursAngle"
16 Storyboard.TargetProperty ="Angle"
17 RepeatBehavior ="Forever" Duration ="12:00:00" />
18 </ Storyboard >
19 </ BeginStoryboard >
20 </ EventTrigger.Actions >
21 </ EventTrigger >
22 </ Canvas.Triggers >
从上述代码中我们可以知道,这个时间触发的事件由 Canvas.Loaded来触发,这个对应的是<Canvas/>的Loaded属性。然后我们通过DoubleAnimation来管理各个控件,Storyboard.TargetName和刚刚画好的控件绑定,将Storyboard.TargetProperty设置为角度"Angle",永远的重复执行,就是将RepeatBehavior设置为Forever,Duration设置为什么时候是才是一圈(可能是这样,太晚了不查资料了...)。接下来要做的就是通过cs文件来控制转速,代码如下,谁都看得懂:
1
public
void
Page_Loaded(
object
o, EventArgs e)
2 {
3 // Required to initialize variables
4 InitializeComponent();
5
6 DateTime date = DateTime.Now;
7 float hourangle = ((( float )date.Hour) / 12 ) * 360 + date.Minute / 2 ;
8 hourangle += 180 ;
9
10 float minangle = ((( float )date.Minute) / 60 ) * 360 ;
11 minangle += 180 ;
12
13 float secangle = ((( float )date.Second) / 60 ) * 360 ;
14 secangle += 180 ;
15
16 HoursAnim.From = hourangle;
17 HoursAnim.To = hourangle + 360 ;
18
19 MinutesAnim.From = minangle;
20 MinutesAnim.To = minangle + 360 ;
21
22 SecondsAnim.From = secangle;
23 SecondsAnim.To = secangle + 360 ;
24 }
2 {
3 // Required to initialize variables
4 InitializeComponent();
5
6 DateTime date = DateTime.Now;
7 float hourangle = ((( float )date.Hour) / 12 ) * 360 + date.Minute / 2 ;
8 hourangle += 180 ;
9
10 float minangle = ((( float )date.Minute) / 60 ) * 360 ;
11 minangle += 180 ;
12
13 float secangle = ((( float )date.Second) / 60 ) * 360 ;
14 secangle += 180 ;
15
16 HoursAnim.From = hourangle;
17 HoursAnim.To = hourangle + 360 ;
18
19 MinutesAnim.From = minangle;
20 MinutesAnim.To = minangle + 360 ;
21
22 SecondsAnim.From = secangle;
23 SecondsAnim.To = secangle + 360 ;
24 }
其实只要你在控件(?应该是叫控件)用x:Name标注,在服务端的InitializeComponent(); 中就会自动为你生产如下代码:Polygon Minutes;...Minutes= this.FindName("Minutes") as Polygon;这样我们就可以直接用了,最后运行一下就OK了。这是我的第一次和SilverLight打交道,如果有什么错误的地方还请多多指教。
本文转自网魂小兵博客园博客,原文链接:http://www.cnblogs.com/xdotnet/archive/2007/06/09/silverlight_gettingstarted_clock.html,如需转载请自行联系原作者