[SilverLight1.1入门] Getting started:模拟时钟

简介:
   很多人都已经开始了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看看他们为我们做好了什么?代码如下:

 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 >

     和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" />

    你可以按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 >

    我们可以按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 

    按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 >

    我们可以看到效果如下:
             
    这个是不会动的始钟,下面我们要做的是就是让时钟走起来,所以要涉及到行为等问题,我们在上面定义时钟指针时都有给他们加入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 >

    从上述代码中我们可以知道,这个时间触发的事件由 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          }

    其实只要你在控件(?应该是叫控件)用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,如需转载请自行联系原作者

相关文章

热门文章

最新文章