SilverLight幻灯片
小弟刚刚开始学习SL,写下这篇入门,希望能抛砖引玉,与各位同学一同进步。高手请绕道。
这里将要介绍一个最简单的幻灯片程序,可以应用在Banner广告或图片播放。图片通过XML传递,配置非常方便。
在这篇文章的代码里,我将配与非常详细的注释,希望能通过代码说明SL的一些问题。
那么就开始吧,先看看最终运行效果:
首先分析下界面的元素结构:
有按钮、半透明的按钮容器、图片控件
东西不多,先从按钮说起:
在工程里创建一个UserControl,命名为TiggerButton,并在XAML中写下如下代码:
1
<Grid x:Name="LayoutRoot" MouseEnter="LayoutRoot_MouseEnter" MouseLeave="LayoutRoot_MouseLeave" Cursor="Hand">2
<Rectangle x:Name="BackGroundRec" Fill="White" RadiusY="4" RadiusX="4" Height="20" Width="45" StrokeThickness="1" Stroke="Blue" />3
<TextBlock x:Name="tb_Number" VerticalAlignment="Center" HorizontalAlignment="Center" Text="1" FontSize="16"/>4
</Grid>
上面代码中,最外层的Grid是自动生成的,它的作用是使得该控件中可以包含多个子元素,因为Grid继承Panel,默认属性是Children,所以可以直接把UIElement放入Grid中。在Grid中注册了MouseEnter和MouseLeave事件,这里的处理方法和Winform,ASP.NET是同出一辄的。
然后的Rectangle就是我们看见的矩形框,框四角的圆角,是由RadiusX和RadiusY指定的。StrokeThickness指定的是边框的宽度。
TextBlock的作用和我们在Winform里遇见的Label非常相似,用于输出字符串。而且Alignment属性也非常好用,直接就指定了该控件的位置,在这里由于没有指定按钮的文字,所以使用了垂直、水平居中。
1
public partial class TiggerButton : UserControl2

{3
//依赖属性4
public static readonly DependencyProperty NumberProperty = DependencyProperty.Register("Number",5
typeof(int),6
typeof(TiggerButton),7
new PropertyMetadata(1));8

9
public ADEntity ADE10

{11
get; set;12
}13

14

/**//// <summary>15
/// 在按钮上显示的数字16
/// </summary>17
public int Number18

{19
get20

{21
return (int) GetValue(NumberProperty);22
}23
set24

{25
SetValue(NumberProperty,value);26
tb_Number.Text = value.ToString();27
}28
}29

30

/**//// <summary>31
/// 构造函数32
/// </summary>33
public TiggerButton(int number,ADEntity ade):this(number)34

{35
ADE = ade;36
}37

38

/**//// <summary>39
/// 构造函数40
/// </summary>41
public TiggerButton(int number):this()42

{43
Number = number;44
}45

46
public TiggerButton()47

{48
InitializeComponent();49
}50

51
private void LayoutRoot_MouseEnter ( object sender, MouseEventArgs e )52

{53
//设置按钮背景透明度54
BackGroundRec.Opacity = 0.5;55
}56

57
private void LayoutRoot_MouseLeave ( object sender, MouseEventArgs e )58

{59
BackGroundRec.Opacity = 1;60
}61

62

/**//// <summary>63
/// 按钮被点击后触发64
/// </summary>65
public event EventHandler onSelected;66

67
private void UserControl_MouseLeftButtonDown ( object sender, MouseButtonEventArgs e )68

{69
if(onSelected!=null)70

{71
onSelected(this, null);72
}73
}74
}
以上代码中,Grid的MouseEnter事件和MouseLeave事件里把矩形框的不透明度设置为0.5和1,以提示按钮被选中。
另外,在整个用户控件里,我还注册了MouseLeftButtonDown事件,并在这个事件里转发我声明的选中事件。
按钮就这样完成了。
然后在工程里创建另一个用户控件:AD,并在XAML中写下如下代码:
<!--最外层容器-->
<Grid x:Name="LayoutRoot">
<!--替换图片1-->
<Image x:Name="Image1"/>
<!--替换图片2-->
<Image x:Name="Image2"/>
<!--按钮容器-->
<Grid x:Name="ContainerGrid" VerticalAlignment="Bottom" Height="40">
<!--容器背景-->
<Rectangle Fill="Black" Opacity="0.3"/>
<!--按钮顺序容器-->
<StackPanel x:Name="ButtonContainer" Orientation="Horizontal">
</StackPanel>
</Grid>
</Grid>
上面的XAML中,描述了幻灯片的工作原理(两个图片控件不停变换透明装,并替换不同的图片),在按钮容器部分,我使用了StackPanel,就不需要对按钮的布局进行更多的控制了。
1
public partial class AD : UserControl2

{3

/**//// <summary>4
/// 幻灯片计时器5
/// </summary>6
DispatcherTimer timer;7

/**//// <summary>8
/// 记录当前显示的AD9
/// </summary>10
public ADEntity currentAD;11

/**//// <summary>12
/// 记录当前正在使用的Image13
/// </summary>14
Image currentImage;15

16

/**//// <summary>17
/// 当前正在显示的AD18
/// </summary>19
public ADEntity CurrentAD20

{21
get22

{23
return currentAD;24
}25
set26

{27
//外界可通过更改值,并显示替换图片的动态效果28
if(!currentAD.Equals(value))29

{30
currentAD = value;31
BeginAnim(value);32
}33
}34
}35

36

/**//// <summary>37
/// AD列表38
/// </summary>39
List<ADEntity> ads = new List<ADEntity>();40

41

/**//// <summary>42
/// 构造方法43
/// </summary>44
public AD ( List<ADEntity> ADs )45
: this ()46

{47
ads = ADs;48
}49

50
public AD()51

{52
InitializeComponent();53
//初始化计时器54
timer=new DispatcherTimer();55
//计时器间隔5秒56
timer.Interval = new TimeSpan(0,0,0,5);57
timer.Tick += timer_Tick;58
timer.Start ();59
}60

61
void timer_Tick ( object sender, EventArgs e )62

{63
for(int i=0;i<ads.Count;i++)64

{65
if(currentAD.Equals(ads[i]))66

{67
//在计时器中循环替换当前AD68
CurrentAD = i==ads.Count-1 ? ads[0] : ads[i + 1];69
break;70
}71
}72
}73

74
private void UserControl_Loaded ( object sender, RoutedEventArgs e )75

{76
for(int i=0;i<ads.Count;i++)77

{78
//加载按钮79
TiggerButton tb = new TiggerButton(i + 1, ads[i]);80
//按钮样式,边距为581
tb.Margin=new Thickness(5);82
tb.onSelected += tb_onSelected;83
ButtonContainer.Children.Add(tb);84
}85
if ( ads.Count > 0 )86

{87
//为当前AD赋初始值88
currentAD = ads[0];89
Image1.Source = new BitmapImage(new Uri(currentAD.Image, UriKind.Relative));90
currentImage = Image1;91
}92
}93

94
void tb_onSelected ( object sender, EventArgs e )95

{96
//按钮被选中后,替换当前AD97
CurrentAD = ((TiggerButton) sender).ADE;98
//重设计时器99
timer.Start();100
}101

102

/**//// <summary>103
/// 播放动画104
/// </summary>105
public void BeginAnim(ADEntity adEntity)106

{107
//构造新故事版108
Storyboard sb_Opacity = new Storyboard();109
//图片隐藏动画110
DoubleAnimation ImageHideAnim = new DoubleAnimation111

{112
//透明度目标为0113
To = 0,114
//1秒动画时间115
Duration = new TimeSpan(0, 0, 1)116
};117
//图片显示动画118
DoubleAnimation ImageShowAnim = new DoubleAnimation119

{120
//透明度目标为1121
To = 1,122
//透明度初始值为0123
From=0,124
Duration = new TimeSpan(0, 0, 1)125
};126
//构造图片URI127
Uri uri = new Uri(adEntity.Image, UriKind.Relative);128
if(currentImage==Image1)129

{130
//为新图片赋值131
Image2.Source = new BitmapImage(uri);132
ImageHideAnim.From = Image1.Opacity;133
//设置动画对象134
Storyboard.SetTarget(ImageHideAnim, Image1);135
Storyboard.SetTarget(ImageShowAnim, Image2);136
//设置当前Image137
currentImage = Image2;138
}139
else if (currentImage==Image2)140

{141
Image1.Source = new BitmapImage(uri);142
ImageHideAnim.From = Image2.Opacity;143
Storyboard.SetTarget(ImageHideAnim,Image2);144
Storyboard.SetTarget(ImageShowAnim,Image1);145
currentImage = Image1;146
}147
//设置动画对象属性148
Storyboard.SetTargetProperty ( ImageHideAnim, new PropertyPath ( "Opacity" ) );149
Storyboard.SetTargetProperty ( ImageShowAnim, new PropertyPath ( "Opacity" ) );150
//把动画添加到故事版中151
sb_Opacity.Children.Add(ImageHideAnim);152
sb_Opacity.Children.Add(ImageShowAnim);153
//开始动画154
sb_Opacity.Begin();155
}156

157
private void UserControl_MouseEnter ( object sender, System.Windows.Input.MouseEventArgs e )158

{159
Storyboard sb = new Storyboard();160
DoubleAnimation da = new DoubleAnimation()161

{162
Duration = new TimeSpan(0,0,1),163
To = 1,164
From = ContainerGrid.Opacity165
};166
Storyboard.SetTarget(da, ContainerGrid);167
Storyboard.SetTargetProperty(da, new PropertyPath("Opacity"));168
sb.Children.Add(da);169
sb.Begin();170
}171

172
private void UserControl_MouseLeave ( object sender, System.Windows.Input.MouseEventArgs e )173

{174
Storyboard sb = new Storyboard();175
DoubleAnimation da = new DoubleAnimation176

{177
Duration = new TimeSpan(0,0,1),178
To = 0,179
From = ContainerGrid.Opacity180
};181
Storyboard.SetTarget(da, ContainerGrid);182
Storyboard.SetTargetProperty(da, new PropertyPath("Opacity"));183
sb.Children.Add(da);184
sb.Begin();185
}186
}
在播放动画的方法中,构造了个故事版,并把TimeLine对象添加进去。
在SL的动画中,有很多类型的TimeLine,这些TimeLine可以指定不同数据类型的变化动画。
在SetTargetProperty方法中,设置的必须是依赖属性。并且这个依赖属性必须是在后台声明的名称,类似
public static readonly DependencyProperty NumberProperty = DependencyProperty.Register("Number",
typeof(int),
typeof(TiggerButton),
new PropertyMetadata(1));
中的Number这个字符串。
XML的读取我就不再赘言了,不过要说明的是SL的运行环境中的XML对象模型,和普通的Framework对象模型完全不同,再也不能用XMLDocument之类的对象了。
这些代码可以在下面的源码中看见:
浙公网安备 33010602011771号